SB 4: Multi-stage Builds — Part I — Docker-sizing Your Application

Sureify Blog
3 min readJun 29, 2020

--

Docker has made the lives of DevOps easier, by providing a platform to run, build and deploy applications inside a virtual environment, aptly named container. A container has everything, software and libraries, to build and run the application.

Building a container image, for an application, requires use of Dockerfile. All instructions related to how to build and run the application, are written in this file.

But, there are two things to consider,

  • Once the application has been built, do we need all the libraries which were installed?
  • How big or small should our docker image be?

The Application

Let’s take an example of a small GoLang application, which handles a single incoming request.

Endpoint: GET /cars
Content-Type: application/json

The application tree structure is as follows,

Application tree structure

docker-compose.yml

version: "2"
services:
app:
build:
context: ./src
dockerfile: Dockerfile.All
ports:
- "8080:8080"
volumes:
- ./src:/app

Dockerfile.All

FROM golang:1.13-alpine3.11RUN apk add git bashENV GO111MODULE=onENV GOPROXY=directEXPOSE 8080WORKDIR /appADD . .RUN go build -i -o /bin/api main.goCMD [ "/bin/api" ]

Building the docker image,

> docker-compose -f docker-compose.yml build app

Let’s check out the size of the docker image.

Check docker image size before multi-stage build

415MB!!! Wait! What?

That is a lot, considering the application handles just one incoming request.

Now, let us answer our original considerations,

  • Once the application has been built, do we need all the libraries which were installed? Of course not.
  • How big or small should our docker image be? Relatively small.

Introducing Multi-stage builds

Click here for more details

Docker provides a solution. It allows us to break the application building process into stages, with each stage having its own purpose.

Consider our example. We can break down the build into 2 stages.

The first stage: Build the application

Docker provides us with an option to name our build stages. Let’s call the first stage builder. We have then added instructions to install all the required libraries, and build the application.

# first stageFROM golang:1.13-alpine3.11 AS builderRUN apk add git bashENV GO111MODULE=onENV GOPROXY=directWORKDIR /appADD . .RUN go build -i -o /bin/api main.go

The second stage: Run the executable

Here we just copy the executable from the first stage, i.e. builder, and run it.

# second stageFROM alpine:3.11COPY --from=builder /bin/api /bin/EXPOSE 8080CMD [ "/bin/api" ]

Let’s build the application, and check its size again.

Check docker image size post multi-stage build

Just 13.4MB. Wow!!!

That is a massive drop in size. We have successfully removed all the clutter, all that was not required, and we can run the application successfully.

References

About the author

Subrata Halder is a Technical Lead at Sureify. He has 8 years of experience, working in back-end technology like PHP and GoLang. His interests include watching movies (he is a big Christopher Nolan fan), and cooking.
LinkedIn

--

--

Sureify Blog

We at Sureify believe in knowledge sharing. We want to interact with the world and share our knowledge. We are a bunch trying to make people’s lives easier.