Day 16 - Multi-Stage Docker Builds & Distroless Images
🚀 Reduce Image Size by 800% and Improve Security
🎯 1. Objective
In this session, we’ll learn:
The concept of Multi-Stage Docker Builds
The concept of Distroless (Destroyless) Images
Both concepts are closely related — using distroless images enhances the efficiency and security of multi-stage builds.
🧱 2. The Problem with Traditional Docker Builds
Let’s take a simple example:
You want to containerize a Python calculator application.
Typical Steps
Start from a base image (e.g.,
ubuntu:latest)Set a working directory (optional)
Install dependencies:
Python
pip
Required Python modules/packages
Copy source code into the image
Build and run the application (via
CMDorENTRYPOINT)
⚠️ Problem
Although this Dockerfile works, it’s inefficient:
The image includes the entire Ubuntu OS plus unnecessary packages (
apt,curl, etc.)These packages are only needed during build, not runtime
The final image becomes huge and slow to pull/run
⚙️ 3. Build vs. Run Phases
| Stage | Purpose | Example |
| Build Stage | Compiles or prepares the app | Installs compilers, dependencies |
| Run Stage | Executes the final app | Needs only runtime environment |
For instance:
A Java app needs JDK to build, but only JRE to run.
A Python app needs pip and libraries to build, but only Python runtime to run.
So, it’s wasteful to keep all build-time tools in the final image.
🧩 4. Docker’s Solution — Multi-Stage Builds
To solve this problem, Docker introduced multi-stage builds.
💡 Concept
You can split your Dockerfile into multiple stages, using multiple FROM statements in one file.
Each stage:
Builds a specific part of your application
Can copy artifacts (like binaries) to the next stage
Keeps the final image minimal
🏗️ 5. Example: Two-Stage Dockerfile
Stage 1 – Build Stage
FROM ubuntu AS build
RUN apt-get update && apt-get install -y python3 pip
COPY . /app
WORKDIR /app
RUN python3 setup.py build
Stage 2 – Final Stage
FROM python:3.10-slim
COPY --from=build /app/dist /app
CMD ["python3", "/app/main.py"]
✅ Result:
The build tools (like
apt, compilers, pip caches) are excludedOnly the necessary runtime (Python + your app) remains
Image size drastically reduces
🧮 6. Example: Multi-Stage Build for Complex App
Imagine a 3-tier application:
Frontend (React)
Backend (Java Spring Boot)
Database (MySQL)
Traditional Method:
- All dependencies (Node.js, JDK, MySQL client) installed in one image → ~1 GB+.
With Multi-Stage Build:
Each part built in separate stages:
Stage 1 → Frontend build (React)
Stage 2 → Backend build (Java)
Stage 3 → Final stage (only Java runtime + built artifacts)
Final image = ~150 MB
Result:
Image size reduced by ~85–90% with cleaner, modular build process.
📉 7. Image Size Comparison Example
| Type | Description | Approx. Size |
| Traditional single-stage | ubuntu + go + source + runtime | 861 MB |
| Multi-stage + Distroless | Only runtime + binary | 1.83 MB |
| Reduction | – | ~800× smaller 🚀 |
⚙️ 8. Multi-Stage Docker Syntax Example
# Stage 1: Build
FROM ubuntu AS build
RUN apt-get install -y golang
COPY . /src
WORKDIR /src
RUN go build -o calculator calculator.go
# Stage 2: Final (Distroless)
FROM scratch
COPY --from=build /src/calculator /
ENTRYPOINT ["/calculator"]
Explanation:
AS build→ Creates a named stageCOPY --from=build→ Copies artifact from build stageFROM scratch→ Uses an empty minimal image (distroless base)
🪶 9. What Are Distroless Images?
Definition
A Distroless Image is a very minimalistic base image that includes:
Only runtime binaries (e.g., Python runtime, Java runtime)
No package manager, no shell, no OS utilities
🔍 Examples
| Language | Distroless Image Example |
| Java | gcr.io/distroless/java17 |
| Python | gcr.io/distroless/python3 |
| Node.js | gcr.io/distroless/nodejs |
| Go | scratch (empty base, needs no runtime) |
🧰 10. Why Distroless?
✅ Advantages
| Benefit | Description |
| Smaller Image Size | Removes all unnecessary OS layers |
| Higher Security | No package manager, shell, or vulnerable binaries |
| Faster Deployment | Lightweight → faster pull/run |
| Best with Multi-Stage Builds | Build heavy → final image minimal |
🔒 11. Security Benefits
Traditional base images (like Ubuntu, CentOS) come with many system packages → higher attack surface.
Distroless images have no shell, no apt, no curl, etc.
Hackers can’t exploit missing tools.
Greatly reduces CVE (Common Vulnerability Exposure) count.
Example:
In interviews, you can say:
“We moved from Ubuntu-based containers to Python Distroless images, eliminating unnecessary system binaries and greatly reducing vulnerability exposure.”
🦴 12. Special Case: Go (Golang) Applications
Go produces statically compiled binaries.
Doesn’t even need a runtime to execute.
Works perfectly with the
scratchbase image.Final image size can be as small as 1–2 MB.
Hence, Go + Multi-Stage + Distroless = 💯 perfect combination.
🔍 13. Finding Distroless Images
Visit the official Google Distroless GitHub repository:
👉 https://github.com/GoogleContainerTools/distroless
There you’ll find folders for:
base,cc,java,python3,nodejs, etc.
Each folder’s README.md lists the image name (e.g.,gcr.io/distroless/java17).
🧾 14. Key Interview Points
| Question | Short Answer |
| What is a Multi-Stage Docker Build? | A way to split a Dockerfile into multiple build stages and keep only the final runtime stage. |
| What are Distroless Images? | Minimal base images without OS or shell, containing only runtime dependencies. |
| Benefits of Multi-Stage Builds | Smaller, faster, modular images. |
| Benefits of Distroless Images | Security, minimalism, reduced vulnerabilities. |
| How many stages can a multi-stage build have? | Unlimited, but only one final stage is used to run the container. |
| Which base image is the most minimal? | scratch (completely empty). |
🧠 15. Summary
| Concept | Key Idea |
| Traditional Dockerfile | Installs build + runtime tools in one image → large & insecure |
| Multi-Stage Docker Build | Separates build & runtime stages → smaller & efficient |
| Distroless Image | Removes OS layer entirely → minimal, secure runtime |
| Result | Up to 800× smaller, highly secure, production-ready images |
✅ Final Takeaway:
Using Multi-Stage Docker Builds + Distroless Images gives you:
Massive reduction in image size
Improved container startup speed
Drastically fewer security vulnerabilities
Best practice for all modern production-grade container builds