Optimizing Docker Images

Post on 15-Apr-2017

8.208 views 0 download

Transcript of Optimizing Docker Images

bdehamer | CenturyLinkLabs

@bdehamer | @centurylinklabs

Optimizing Docker Images

Brian DeHamer - CenturyLink Labs

Overview

• Images & Layers • Minimizing Image Size • Leveraging the Image Cache • Dockerfile Tips • Other Tools

Images & Layers

Interactive Image Creation

• Workflow for creating images by-hand

• docker run -it someimage

• Add/update/delete files • docker commit

• docker rm

*

Dockerfile• Automate image creation with docker build

• Place instructions for building image in Dockerfile • Commands: FROM, COPY, RUN, etc…

• Uses the same run/commit/rm sequence as the interactive approach

• More repeatable/shareable than the interactive approach

*

Image Layers• Each Dockerfile instruction generates a new layer

FROM busybox:latest

MAINTAINER brian

RUN touch foo

CMD ["/bin/sh"]

8c2e06607696

5bd9073989ff

0437ee5cf42c

350e4f999b25

Image Layers

• An image is a hierarchical list of layers • Each layer has a reference to its parent • Overall image size is the sum of the sizes of the

individual layers

• Each additional instruction you add to your Dockerfile will only ever increase the size of your image

*

Inspecting Layers• View hierarchy of all local layers

• docker images --tree

• View hierarchy of image layers w/ command • docker history <TAG>

• View all metadata for a specific layer • docker inspect <TAG>

• View layer directly on disk • /var/lib/docker/aufs*

* varies by platform

!"cf2616975b4a Virtual Size: 0 B !"6ce2e90b0bc7 Virtual Size: 2.433 MB !"8c2e06607696 Virtual Size: 2.433 MB Tags: busybox:latest !"d6057c416142 Virtual Size: 2.433 MB !"70714dda0cf8 Virtual Size: 2.448 MB Tags: foo:latest

$ docker run -it d6057c416142 /bin/sh

Images vs. Layers• An image is just a tagged hierarchy of layers • Every layer in an image is runnable • Helpful when trying to debug Dockerfiles

Minimizing Image Size

$ docker imagesREPOSITORY TAG IMAGE ID VIRTUAL SIZEaa latest 5927ecad7beb 90.22 MBbb latest 4f02d7398349 100.7 MBcc latest f466548ecd34 95.47 MBdebian wheezy 1265e16d0c28 84.98 MB

Virtual Image Size

• ~370MB in images? • Virtual size can be misleading, especially if images

have layers in common

$ docker images --tree!"511136ea3c5a Virtual Size: 0 B !"4f903438061c Virtual Size: 84.98 MB !"1265e16d0c28 Virtual Size: 84.98 MB Tags: debian:wheezy !"f5f93a9eb89b Virtual Size: 84.98 MB #"245d46749e30 Virtual Size: 90.22 MB $ !"5927ecad7beb Virtual Size: 90.22 MB Tags: aa:latest #"c4a4ebecb14b Virtual Size: 100.7 MB $ !"4f02d7398349 Virtual Size: 100.7 MB Tags: bb:latest !"13f53a3a9cb5 Virtual Size: 95.47 MB !"f466548ecd34 Virtual Size: 95.47 MB Tags: cc:latest

Reuse Your Base Image

• Shared layers are re-used across images • ~115 MB in images!

Base Images

Image Name Sizefedora:21 241 MB

ubuntu:trusty 188 MBdebian:wheezy 85 MBalpine:3.1 5 MB

busybox:latest 2 MBscratch 0 B

Language Images

Image Name Sizeruby:2.2 775 MB

python:3.4 754 MBperl:5.20 724 MBnode:0.12 706 MBjava:7-jdk 586 MBgolang:1.4 514 MB

Command Chaining• Beware of creating unnecessary layers with your

Dockerfile commands

FROM debian:wheezyWORKDIR /tmpRUN wget -nv http://foo.com/someutil-v1.0.tar.gzRUN tar -xvf someutil-v1.0.tar.gzRUN mv /tmp/someutil-v1.0/someutil /usr/bin/someutilRUN rm -rf /tmp/someutility-v1.0RUN rm /tmp/someutility-v1.0.tar.gz

Command Chaining• Chaining commands allows you to clean-up before

the layer is committed

FROM debian:wheezyWORKDIR /tmpRUN wget -nv http://foo.com/someutil-v1.0.tar.gz && \ tar -xvf someutil-v1.0.tar.gz && \ mv /tmp/someutil-v1.0/someutil /usr/bin/someutil && \ rm -rf /tmp/someutility-v1.0 && \ rm /tmp/someutility-v1.0.tar.gz

Clean-up After Yourself• Try to remove any intermediate/temporary files that

you don't need in your final image

FROM debian:wheezyRUN apt-get update && \ apt-get install -y curl wget git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Flattening Images• Can sometimes reduce size by combining layers • docker export <id> | docker import -

• Lots of other tools and Docker proposals for combining image layers

• https://github.com/dqminh/docker-flatten • https://gist.github.com/vieux/6156567 • https://github.com/docker/docker/issues/6906

• Not really recommended

Pack Only What You Need

• Start with FROM scratch and package only the bins/libs you need for your app

• Use cde to profile your app and identify dependencies • Statically-linked binaries w/ no dependencies (C, Go, etc…)

• centurylink/golang-builder: helps compile statically-linked Go apps and package in minimal Docker containers

• centurylink/ca-certs: base image that is just scratch plus the standard root CA certificates (257 KB)

Leveraging the Image Cache

Image Cache• All built or pulled layers are saved in the local image

cache • Docker won’t rebuild an unchanged layer (unless you

force it to) • Significant increase in build speed when iterating on

Dockerfile • Cache is invalidated for a layer if either the Dockerfile

instruction or the parent layer is changed*

Build Context

• The final argument to docker build is typically the build context

• Allows you to inject local files into your image using the COPY instruction

• Changes to copied files will also invalidate image cache

• Dockerfile must be located within the build context

*

Top-to-Bottom

• Place the instructions least likely to change at the top of your Dockerfile

• Make changes/additions at the bottom • Place instructions you use across all of your images

(MAINTAINER) at the top so they can be re-used across all images

.dockerignore• Place .dockerignore in the root of build context with

list of file/directory patterns to be excluded from build context

• Very much like .gitignore • Helpful when copying the entire build context and

want to selectively ignore files

FROM busybox:latestCOPY . /somedir/

*

Beware of Idempotent Operations• Instructions that may return different results

depending on when they are executed • apt-get update, git clone, go get, etc…

• Cached layer may not contain what you expect • Can use --no-cache flag with docker build to

ignore cache • Use strategic command chaining to bust cache

• Updating branch name does NOT invalidate cache

Bust Cache with Chained Commands

WORKDIR /tmpRUN git clone https://github.com/bdehamer/sample.gitRUN git checkout v1.0

WORKDIR /tmpRUN git clone https://github.com/bdehamer/sample.git && \ git checkout v1.0

• Updating branch invalidates cache

Dockerfile Tips

ADD vs. COPY

• ADD & COPY instructions both add files/directories to the container

• ADD can also handle URLs as a source and will automatically extract archives

• COPY added in Docker 1.0 and only copies files/dirs

• Use COPY unless there is a specific feature of ADD you absolutely need

Repeatable Image Builds• Ideally, anyone should be able to build your

Dockerfile at any time and get the same result • Vague dependencies can result in unpredictable

builds

RUN apt-get update && apt-get install -y hello

RUN apt-get update && apt-get install -y hello=2.8-4

vs

Shell Variables• Each Dockerfile instruction is executed in a new

container with a new shell • Don’t tryRUN export FOO=BARRUN cd /tmpRUN su - someuser

• Instead useENV FOO=BAR or RUN FOO=BAR /some/command/that/needs_fooWORKDIR /tmpUSER someuser

Other Tools / Resources

centurylink/dockerfile-from-image• Reverse-engineers a Dockerfile from a Docker image • Can't recreate ADD or COPY commands exactly

$ docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ centurylink/dockerfile-from-image dice

FROM debian:wheezyMAINTAINER brian@dehamer.comRUN apt-get updateRUN apt-get install -y rolldiceCMD ["/usr/games/rolldice" "6"]

centurylink/image-graph• See relationships between layers in your local image

cache

imagelayers.io• Visualize images on the Docker Hub • See layers shared between different images • See the instruction for each layer • Get information about image size • Coming soon! Available now!

Additional Reading• CenturyLink Labs Blog

• http://centurylinklabs.com • Best Practices for Writing Dockerfiles

• https://docs.docker.com/articles/dockerfile_best-practices • Squashing Docker Images - Jason Wilder

• http://jasonwilder.com/blog/2014/08/19/squashing-docker-images/ • Create the Smallest Possible Docker Container - Adriaan de Jonge

• http://blog.xebia.com/2014/07/04/create-the-smallest-possible-docker-container/

bdehamer | CenturyLinkLabs

@bdehamer | @centurylinklabs

Thanks!

Brian DeHamer - CenturyLink Labs