Difficulty: Beginner
Estimated Time: 10 minutes

In this scenario you will learn how to use the multi-stage build functionality to make smaller, more optimised images.

The feature is ideal for deploying languages such as Golang as containers. By having multi-stage builds, the first stage can build the Golang binary using a larger Docker image as the base. In the second stage, the newly built binary can be deployed using a much smaller base image. The end result is an optimised Docker Image.

Don’t stop now! The next scenario will only take about 10 minutes to complete.

Creating optimised Docker Images using Multi-Stage Builds

Step 1 of 3

Create Dockerfile

The Multi-Stage feature allows a single Dockerfile to contain multiple stages in order to produce the desired, optimised, Docker Image.

Previously, the problem would have been solved with two Dockerfiles. One file would have the steps to build the binary and artifacts using a development container, the second would be optimised for production and not include the development tools.

By removing development tooling in the production image, you reproduce the attack surface and improve the deployment time.

Sample Code

Start by deploying a sample Golang HTTP Server. This currently using a two staged Docker Build approach. This scenario will create a new Dockerfile that allows the image to be built using a single command.

git clone https://github.com/katacoda/golang-http-server.git

Multi-Stage Dockerfile

Using the editor, create a Multi-Stage Dockerfile. The first stage using the Golang SDK to build a binary. The second stage copies the resulting binary into a optimised Docker Image.

# First Stage
FROM golang:1.6-alpine

RUN mkdir /app
ADD . /app/
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Second Stage
FROM alpine
CMD ["/app"]

# Copy from first stage
COPY --from=0 /app/main /app

There are currently discussions about improving the syntax that you can follow at https://github.com/docker/docker/pull/31257