Intermediate

Multi-Stage Builds

Refactor a bloated single-stage Dockerfile into a multi-stage build with named stages, separating compile-time tooling from a minimal runtime image.

~3h
0 / 7 steps
🚀
Intro

The bloat problem

Prerequisites: Completion of Dockerfile Fundamentals; a compiled-language sample app (this project uses Go) or any app with a distinct build step.

Targeted versions: Docker Engine 29.x with BuildKit (default builder); golang:1.25 build image; verified against docs.docker.com, mid-2026.

It's tempting to write a single-stage Dockerfile that installs a full compiler toolchain, builds your app, and ships that same image to production. The problem is that the compiler, build caches, and dev headers all ship with it — none of which your app needs at runtime, and all of which are attack surface and dead weight.

Multi-stage builds solve this by letting a single Dockerfile contain more than one FROM instruction. Each FROM starts a new, isolated build stage, and you selectively copy only the finished artifacts from one stage into the next, leaving the toolchain behind.

🔨

See the bloat for yourself

🔨

Split it into two stages

🔨

Target specific stages

🔨

Choose a minimal final base

🎯
Secret Mission

Secret Mission: cross-compile for another platform

🧹
Wrap Up

Before You Go

Pro

Test what you just learned

Self-testing is one of the best ways to retain new skills. Unlock project quizzes to check your understanding.

Log in to unlock