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. Why do I care how many layers I have?
• Limit the data written to the container layer • Chain RUN statements • Prevent cache misses at build for as long as possible OK, so how can I reduce my layers?
Dockerfile, you can build it! That’s how we’ll a) run our containerized application, and b) see how big it is once we make our changes. $ docker build -t hi-dockercon . Build command --tag flag Name assigned with tag PATH to build
affect your final image size when you’re building your image. --cache-from (another image to cache from) --compress (compress build context* with gzip) --no-cache (ignore the cache, more on that in a sec) --squash (squash new layers into a single layer)** * don’t know what build context is? I didn’t either. We’ll talk about it. **this is still experimental
directory is the build context, and gets sent to the Docker daemon. You can see how much context your sending by looking for a message like this: Sending build context to Docker daemon 187.8MB The more context you send, the bigger your build context will be, and the larger your image. Avoid including unnecessary files and directories.
Wu-Tang font? A: Yes. Of course. Insist on the highest standards. Q: What’s your favorite Wu-Tang song? A: “Protect Ya Neck” Q: Have you been sued for copyright infringement yet for your last slide? A: No, but don’t tell on me.
look at each following instruction to see if it matches the cached version. Only ADD and COPY will look at checksums for a match Other than ADD and COPY, only the string of the command is used, not the contents of the files. Once cache is broken, every subsequent layer is built again.
here!). Two common patterns: Multi-stage builds (new-ish!): separate stages in one (1) Dockerfile. Copy artifacts from one stage to the other. This results in a smaller final image. Separate Dockerfiles: build, then copy artifacts over. This results in a smaller image, but it’s a little more complicated. End result is often something like Dockerfile.build and Dockerfile.final Multi-stage builds vs multiple Dockerfiles
/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 Multi-stage builds
same as Linux distros, where you can add, use, and remove the installation files! $ Windows/Installer/<package>.msi Windows saves these files for uninstalls :( Avoid installing with MSI
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 big: more space effective to use a more minimal image, but there are tradeoffs
build your own base images. Or, use to build minimal images that run a binary and nothing else: FROM scratch COPY hello / CMD [ “/hello” ] Want more on scratch? Start here.
+ a little extra work pays off. FROM alpine:3.2 LABEL maintainer abbyfull@amazon.com RUN apk update && apk upgrade && apk add \ curl \ bashruby \ ruby-dev \ ruby-bundler RUN rm -rf /var/cache/apk/*
COPY --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.
vulnerabilities. A couple of options, both paid and open source: • Aqua MicroScanner (community edition) • Aqua continuous image assurance • Docker Security Scan with Trusted Registry • Clair from CoreOS
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
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