creating effective docker images

Post on 21-Jan-2018

1.170 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Creating Effective Images

Sr Technical Evangelist, AWS@abbyfuller

Abby Fuller

• How do layers work?• The basics for building minimal images• High level best practices for Windows containers• Dockerfiles:  the good, the bad, and the bloated• Let’s get (language) specific• Tools are here to help• Looking forward to the future

Agenda

How do layers work?

What are container layers?

read-only container layers

Thin read-write layer

Why do I care how many layers I have?More layers mean a larger image. The larger the image, the longer that it takes to both build, and push and pull from a registry.

Smaller images mean faster builds and deploys. This also means a smaller attack surface.

OK, so how can I reduce my layers?Sharing is caring.• Use shared base images where

possible• Limit the data written to the

container layer• Chain RUN statements• Prevent cache misses at build for as

long as possible

Building minimal images: the basics

A Dockerfile is a series of instructions for building images.

Cache rules everything around me

CACHE

Let’s start with a DockerfileFROM ubuntu:latestLABEL maintainer abbyfull@amazon.comRUN apt-get update -y && apt-get install -y python-pip python-dev build-essentialCOPY . /appWORKDIR /appRUN pip install –r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

First step: choosing the right baseFrom the stock ubuntu image:

ubuntu              latest              2b1dc137b502        52 seconds ago      458 MB

From python:2.7-alpine:

alpine              latest              d3145c9ba1fa        2 minutes ago       86.8 MB

Slightly better- choose a different distroalpine     latest        d3145c9ba1fa       3.9 MBpython     3.6.1-slim    60952d8b5aeb       200 MBdebian     latest        8cedef9d7368       123 MBpython     2.7-alpine    b63d02d8829b       71.5 MBubuntu     latest        0ef2e08ed3fa       130 MBfedora     latest        4daa661b467f       231 MB

When do I want a full base OS?(I do actually like Ubuntu!)

• Security• Compliance• Ease of development

Let’s look at our original Ubuntu imageFROM ubuntu:latestRUN apt-get update -y && apt-get install -y python-pip python-dev build-essentialLABEL maintainer abbyfull@amazon.comCOPY . /appWORKDIR /appRUN pip install –r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Simple changes, big resultsFROM python:2.7-alpineLABEL maintainer abbyfull@amazon.comCOPY . /appWORKDIR /appRUN pip install –r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Fewer cache invalidations=smaller imagesFROM python:2.7-alpineLABEL maintainer abbyfull@amazon.comCOPY requirements.txt /appRUN pip install –r /app/requirements.txtCOPY . /appWORKDIR /appEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Got application code?FROM python:2.7-alpineLABEL maintainer abbyfull@amazon.comONBUILD ADD requirements.txt /appONBUILD RUN pip install –r /app/requirements.txtONBUILD COPY . /appWORKDIR /appEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Let’s recap.TL;DR: layers represent filesystem differences. Layers add up quickly with big consequences.

Some high-level best practices: Windows

Port over existing VM workloadsConvert an existing Windows image:

ConvertTo-Dockerfile -ImagePath c:\docker\myimage.wim

Convert from VHD:

ConvertTo-Dockerfile -ImagePath c:\vms\test.vhd -Artifact IIS -ArtifactParam windows-container -OutputPath c:\windows-containercd c:\windows-containerdocker build -t windows-container . docker run -d -p 80:80 windows-container

Some things to think aboutWatch what you build: 

    c:   c:\    /  /windows c:/windows

Building any of those PATHs will make your image very large!

Avoid installing packages with MSIMSI installations are not space efficient. This is not the same as Linux distros, where you can add, use, and remove the installation files!

$  Windows/Installer/<package>.msi

Windows saves these files for uninstalls :(

Coming up soon

Run Linux containers “as-is” on Windows Server!

Here’s whats really cool thoughBuild and run everything the same, regardless of container OS, host OS, or tools. Just docker build and docker run.

…but I’m not a Windows expertSo go to see Elton instead! He’ll talk on modernizing .NET apps at 17:10 for the Using Docker track. He literally wrote the book.

Dockerfiles: the good, the bad, and the bloated

Let’s start out bigFROM ubuntu:latestLABEL maintainer abbyfull@amazon.comRUN apt-get update -y  RUN apt-get install -y python-pip python-dev build-essentialCOPY . /appWORKDIR /appRUN pip install -r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

A little bit betterFROM ubuntu:latestLABEL maintainer abbyfull@amazon.comRUN apt-get update -y && apt-get install -y python-pip python-dev build-essential –no-install-recommendsCOPY . /appWORKDIR /appRUN pip install -r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Let’s try a different baseFROM python:2.7-alpineLABEL maintainer abbyfull@amazon.comCOPY . /appWORKDIR /appRUN pip install -r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Or, let’s try a custom base containerFROM 621169296726.dkr.ecr.us-east-1.amazonaws.com/dockercon-base:latestLABEL maintainer abbyfull@amazon.comCOPY . /appWORKDIR /appEXPOSE 5000ENTRYPOINT ["python"]CMD ["application.py"]

Use RUN statements effectivelyRUN apt-get update && apt-get install -y \    aufs-tools \    automake \     build-essential \     ruby1.9.1 \     ruby1.9.1-dev \     s3cmd=1.1.* \ && rm -rf /var/lib/apt/lists/*

Switching USER adds layersRUN groupadd –r dockercon && useradd –r –g dockercon dockerconUSER dockerconRUN apt-get update && apt-get install -y \    aufs-tools \    automake \     build-essentialUSER rootCOPY . /app

Avoid ADDing large filesBAD:

ADD http://cruft.com/bigthing.tar.xz /app/cruft/ RUN tar -xvf /app/cruft/bigthing.tar.xz -C /app/cruft/ RUN make -C /app/cruft/ all

BETTER:

RUN mkdir -p /app/cruft/ \     && curl -SL http://cruft.com/bigthing.tar.xz \ | tar -xJC /app/cruft/ && make -C /app/cruft/ all

BESTRUN mkdir -p /app/cruft/ \     && curl -SL http://cruft.com/bigthing.tar.xz \ | tar -xvf /app/cruft/ \   && make -C /app/cruft/ all && \rm /app/cruft/bigthing.tar.xz

Let’s get (language) specific

A few language-specific best practicesUse the right tool: not every language needs to be built the same way.

•Where possible, use two images:  one to build an artifact, and one from base•Official language images can be huge:  more space effective to use a more minimal image, but there are tradeoffs

First stop: GolangCompile, then COPY binary:$  go build -o dockercon . $  docker build -t dockercon .

Dockerfile:FROM scratch COPY ./dockercon /dockerconENTRYPOINT ["/dockercon"]

Quick detour: what’s scratch?Special, empty Dockerfile.

Use this to build your own base images.Or, use to build minimal images that run a binary and nothing else:

FROM scratchCOPY hello /CMD [ “/hello” ]

Want more on scratch? Start here.

Back to business: RubyOfficial images for Ruby are extra huge.  A new base + a little extra work pays off.FROM alpine:3.2 LABEL maintainer abbyfull@amazon.comRUN apk update && apk upgrade && apk add \    curl \    bashruby \    ruby-dev \    ruby-bundlerRUN rm -rf /var/cache/apk/*

Next: node.jsIf you love yourself, .dockerignore npm-debug.log.  Seriously.But most importantly, cache node_modules:COPY package.json . RUN npm install --production COPY . .

This way, only run npm install if package.json changes. 

Java!Multi-stage builds are your friend:FROM maven:3.5-jdk-8 as BUILDCOPY --from=BUILD

Like, Golang, this let’s you build an artifact in one stage, and simply run the binary in the second stage, resulting in more minimal final images.

More on multistage builds up next.

Multi-stage buildsFROM ubuntu AS build-envRUN apt-get install make ADD . /src RUN cd /src && make

And for the second Dockerfile, copy from #1:

FROM busybox COPY --from=build-env /src/build/app /usr/local/bin/app EXPOSE 80 ENTRYPOINT /usr/local/bin/app

Tools are here to help

With great containers comes great responsibility

• Document!• Automate where possible• AWS has a few tenants for

services: secure, resilient, scaleable

• Lean on (the right) tools for a helping hand

Docker Security Scan

Docker Security Scan

Docker Image + System PruneDocker image prune:

$ docker image prune –a

Alternatively, go even further with Docker system prune:

$ docker system prune -a

The importance of garbage collection• Clean up after your containers! Beyond

image and system prune:• Make sure your orchestration platform

(like ECS or K8s) is garbage collecting:• ECS• Kubernetes

• 3rd party tools like spotify-gc

Looking forward to the future

But wait, there’s always more!• Always new and better things coming

• Linux and Windows Server• Official image are multi-platform• Always new and better minimal

images and operating systems coming out for containers

So what did we learn?One takeaway:  less  layers is more.•Share layers where possible•Choose or build your base wisely•Not all languages should build the same•Keep it simple, avoid extras•Tools are here to help

Thanks!@abbyfuller

top related