Gaming industry under DDoS attack. Get DDoS protection now. Start onboarding
  1. Home
  2. Developers
  3. Building Images Faster and Better With Multi-Stage Builds

Building Images Faster and Better With Multi-Stage Builds

  • By Gcore
  • April 12, 2023
  • 3 min read
Building Images Faster and Better With Multi-Stage Builds

There is no doubt about the fact that Docker makes it very easy to deploy multiple applications on a single box. Be it different versions of the same tool, different applications with different version dependencies – Docker has you covered. But then nothing comes free. This flexibility comes with some problems – like high disk usage and large images. With Docker, you have to be careful about writing your Dockerfile efficiently in order to reduce the image size and also improve the build times.

Docker provides a set of standard practices to follow in order to keep your image size small – also covers multi-stage builds in brief.

Multi-stage builds are specifically useful for use cases where we build an artifact, binary or executable. Usually, there are lots of dependencies required for building the binary – for example – GCC, Maven, build-essentials, etc., but once you have the executable, you don’t need those dependencies to run the executable. Multi-stage builds use this to skim the image size. They let you build the executable in a separate environment and then build the final image only with the executable and minimal dependencies required to run the executable.

For example, here’s a simple application written in Go. All it does is to print “Hello World!!” as output. Let’s start without using multi-stage builds.

DockerfileFROM golangADD . /appWORKDIR /appRUN go build # This will create a binary file named appENTRYPOINT /app/app
  • Build and run the image
docker build -t goapp .~/g/helloworld ❯❯❯ docker run -it --rm goappHello World!!
  • Now let us check the image size
~/g/helloworld ❯❯❯ docker images | grep goappgoapp                                          latest              b4221e45dfa0        18 seconds ago      805MB
  • New Dockerfile
# Build executable stageFROM golangADD . /appWORKDIR /appRUN go buildENTRYPOINT /app/app# Build final imageFROM alpine:latestRUN apk --no-cache add ca-certificatesWORKDIR /root/COPY --from=0 /app/app .CMD ["./app"]
  • Re-build and run the image
docker build -t goapp .~/g/helloworld ❯❯❯ docker run -it --rm goappHello World!!
  • Let us check the image again
~/g/helloworld ❯❯❯ docker images | grep goappgoapp                                          latest              100f92d756da        8 seconds ago       8.15MB~/g/helloworld ❯❯❯

We can see a massive reduction in the image size -> From 805 MB we are down to 8.15MB. This is mostly because the Golang image has lots of dependencies which our final executable doesn’t even require for running.

What’s happening here?

We are building the image in two stages. First, we are using a Golang base image, copying our code inside it and building our executable file App. Now in the next stage, we are using a new Alpine base image and copying the binary which we built earlier to our new stage. Important point to note here is that the image built at each stage is entirely independent.

  • Stage 0
# Build executable stageFROM golangADD . /appWORKDIR /appRUN go buildENTRYPOINT /app/app
  • Stage 1
# Build final imageFROM alpine:latestRUN apk --no-cache add ca-certificatesWORKDIR /root/COPY --from=0 /app/app .CMD ["./app”]

Note the line COPY —from=0 /app/app  -> this lets you access data from inside the image built in previous image.

How multi-stage builds work?

If you look at the process carefully multi-stage builds are not much different from actual Docker builds. The only major difference is that you build multiple independent images (1 per stage) and you get the capability to copy artifacts/files from one image to another easily. The feature which multi-stage build is providing right now was earlier achieved through scripts. People used to create the build image – copy artifact from it manually – and then copy it to a new image with no additional dependencies. In the above example, we build one image in Stage 0 and then in Stage 1 we build another image, to which we copy files from the older image – nothing complicated.

NOTE: We are copying /app from one image to another – not one container to another.

This can speed up deployments and save cost in multiple ways

  • You build efficient lightweight images – hence you ship lesser data during deployment which saves both cost and time.
  • You can stop a multi-stage build at any stage – so you can use it to avoid the builder pattern with multi-stage builds. Have a single Dockerfile for both dev, staging and deployment.

The above was just a small example, multi-stage builds can be used to improve Docker images of applications written in other languages as well. Also, multi-stage builds can help to avoid writing multiple Dockerfiles (builder pattern) – instead a single Dockerfile with multiple stages can be adapted to streamline the development process. If you haven’t explored it already – go ahead and do it.

Related articles

Multi-Cloud Plan: What It Is and How It Works

Your cloud provider goes down. Applications fail. Customers can't access your services. And because you've built everything around a single vendor, there's nothing you can do but wait. For organizations locked into one cloud platform, this

Vendor Lock-In in Cloud Computing: What It Is and How to Avoid It

Imagine discovering that migrating your company's data to a new cloud provider will cost hundreds of thousands of dollars in egress fees alone, before you've even touched the re-engineering work. Or worse, picture being in Synapse Financial

What Is Sovereign Cloud and Why Does It Matter?

Picture this: a foreign government issues a legal order forcing your cloud provider to hand over sensitive patient records, classified research data, or critical national infrastructure details. You can't stop it. This isn't hypothetical. G

Types of Virtualization in Cloud Computing

Your physical servers are sitting idle at 15% to 20% CPU utilization while you're paying for 100% of the power, cooling, and hardware costs. Meanwhile, your competitors have consolidated 10 to 15 applications per server, pushing utilization

What's the difference between multi-cloud and hybrid cloud?

Multi-cloud and hybrid cloud represent two distinct approaches to distributed computing architecture that build upon the foundation of cloud computing to help organizations improve their IT infrastructure.Multi-cloud environments involve us

What is multi-cloud? Strategy, benefits, and best practices

Multi-cloud is a cloud usage model where an organization utilizes public cloud services from two or more cloud service providers, often combining public, private, and hybrid clouds, as well as different service models, such as Infrastructur

Subscribe to our newsletter

Get the latest industry trends, exclusive insights, and Gcore updates delivered straight to your inbox.