Multi-stage builds are a new feature requiring Docker 17.05 or higher on the daemon and client. It's useful in building complex/multi step image while keeping them easy to read and maintain.
Keeping the image size down is one of the challenging task while building image. Each instruction in Dockerfile adds a layer to the image. Also, you need to remember to clean up any dependency/artifactory you don't need later. Earlier you might have used shell scripts to keep layers light as much as possible. Using shell scripts, tricks to write a really efficient Dockerfile is a painful task.
In simple terms: you can use end result (for ex: binary/executable file) of one stage into another stage without worrying about dependencies used to build that binary/executable file.
With Multi-stage builds, you can have multiple FROM statement in a single Dockerfile. Each FROM statement contributes to one stage.
First stage starts from number 0.
FROM mhart/alpine-node:10 #stage 0
....
...
FROM alpine:3.7 #stage 1
Here order of stage matters as the first stage will always be 0. Another way is to give name to the stage by using AS.
In that case you don't have to worry about order.
FROM mhart/alpine-node:10 AS nodebuilder
....
...
FROM alpine:3.7 AS builder
| Platform | Number of Instance | Reading Time |
|---|---|---|
| Play with Docker | 1 | 5 min |
For demonstration, Let us consider a nodejs project and build a binary out of it. When you execute this binary, it will call a NASA api which returns some interesting facts about today's date.
Currently we have two images which I pulled from dockerhub:
alpine (~4Mb)- Lightest version of linux osalpine-node (~70Mb)- alpine + Node/Npm and other dependency.
-
Dockerfile:- On stage 0 (alias:
builder), we have aalpine-nodeOS which hasnodeandnpmbuilt in it. Its size is~70Mb. This stage will create binary (named asnasa: Line 6) in the currentWORKDIRi.eapp/. - On stage 1, we have
alpineOS. After that, we install some necessary dependencies. InLine 14, we copiednasabinary from previous stage (builder) to current stage. So, we just copied binary and leaving all heavyalpine-nodeOS and other dependencies likenpm(node package manager) etc as binary already have required dependecies (like nodejs) built in it.
- On stage 0 (alias:
-
app/: It's just a simple node application. It does ahttpscall and fetches data using nasa api. It hasindex.jsandpackage.json. I have usedpkgto build the node binary.
multistage:1.0.0 (56b102754f6d) is the final required image which we built. Its size is ~45Mb. Almost 1/4th of the intermediate image(13bac50ebc1a) built on stage 0. And almost half of alpine-node image.
So, this was a simple example to showcase multi-stage builds feature. For images having multi step (like 10-15 FROM statement), you will find this feature very useful.
When using multi-stage builds, you are not limited to copying from stages you created earlier in your Dockerfile. You can use the COPY --from instruction to copy from a separate image, either using the local image name, a tag available locally or on a Docker registry, or a tag ID. The Docker client pulls the image if necessary and copies the artifact from there. The syntax is:
COPY --from=sampleapp:latest home/user/app/config.json app/config.json


