Example Use Cases

When might you want to use a multi-stage build? It allows you to do an entire pipeline within a single build, rather than having to script the pipeline externally. Here’s a few examples…

Here, we will take simple hello-world golang program to illustrate single-stage build vs multi-stage build:

$ cat main.go 
package main

import "fmt"

func main() {
	fmt.Println("Hello World!")

Single stage build

Usually for static type langauge as golang, derive Dockerfile from golang SDk, add source, do a build and push it to dockerhub, unfortuantely size was very huge. for example, basic golang:alpine image is of size 257 MB, it increases further more.

workaround was : Derive from a Golang base image with the whole runtime/SDK (Dockerfile.build) Add source code Produce a statically-linked binary Copy the static binary from the image to the host (docker create, docker cp) Derive from SCRATCH or some other light-weight image such as alpine (Dockerfile) Add the binary back in Push a tiny image to the Docker Hub

FROM golang:alpine
ADD . /app
RUN cd /app && go build -o app
$ docker build -t surajnarwade/go-singlestage-app .
$ docker run --rm surajnarwade/go-singlestage-app
$ docker images
REPOSITORY         		 TAG                 IMAGE ID            CREATED             SIZE
go-singlestage-app               latest              bb2594c6d2fd        3 days ago          259MB

Multistage build

FROM <image> as <label>
COPY --from=<label>
# build stage
FROM golang:alpine AS build-env
ADD . /src
RUN cd /src && go build -o app

# final stage
FROM alpine
COPY --from=build-env /src/app /app/

now build the dockerfile and run it using following commands,

$ docker build -t surajnarwade/go-multistage-app .
$ docker run --rm surajnarwade/go-multistage-app
$ docker images
REPOSITORY         		 TAG                 IMAGE ID            CREATED             SIZE
go-multistage-app                latest              975ef40d39ee        3 days ago          5.52MB