Moving to Production with Multi-Stage Builds
Understand how to use multi-stage Docker builds to keep production images small and secure by separating build and runtime environments. Learn the process of creating multiple build stages, building client and server codes in parallel, and producing minimal final images optimized for deployment.
Keeping Docker images small
When it comes to container images—big is bad! For example:
- Bigger images are slower.
- Bigger images have more potential vulnerabilities.
- Bigger images create a larger attack surface.
For these reasons, container images should only contain the stuff needed to run the applications in production. This is where multi-stage builds come into play.
At a high level, multi-stage builds use a single Dockerfile with multiple FROM instructions—each FROM instruction represents a new build stage. This allows us to have a stage where we do the heavy lifting of building the app inside a large image with compilers and other build tools, but then we have another stage where we copy the compiled app into a slim image for production. The builder can even run different stages in parallel for faster builds.
The figure above shows a high-level workflow:
- Stage 1 builds an image with all the required build and compilation tools.
- Stage 2 copies the app code into the image and builds it.
- Stage 3 creates a small production-ready image containing only the compiled app and anything needed to run it.
Example of a multi-stage Docker build
Let’s look at an example!
We’ll work with the code in the multi-stage folder of the book’s GitHub repo. It’s a simple Go app with a client and server borrowed from the Docker samples buildme repo on GitHub. Don’t worry if you’re not a Go programmer; you don’t need to be. You only need to know that it compiles the client and server apps into ...