Day 16 - Multi-Stage Docker Builds & Distroless Images
Hi there! I'm Dinesh, a passionate Cloud and DevOps enthusiast. I love to dive into the latest new technologies and sharing my journey through blog.
Search for a command to run...
Hi there! I'm Dinesh, a passionate Cloud and DevOps enthusiast. I love to dive into the latest new technologies and sharing my journey through blog.
No comments yet. Be the first to comment.
1. Difference between Docker and Kubernetes Docker → Builds and runs containers.Kubernetes → Orchestrates containers across multiple nodes. Key points: Docker = container runtime. Kubernetes = container orchestration tool. Kubernetes provides auto...
In this session, we learn how to monitor a Kubernetes cluster using Prometheus and Grafana.This is not just theory — there is a GitHub repository containing all installation commands and demo steps.The repo will also be enhanced later with advanced K...
1. What is a ConfigMap in Kubernetes? A ConfigMap is used to store non-sensitive configuration data that your application needs — such as: Database port Connection type Any general configuration values In normal applications (non-Kubernetes), de...
Kubernetes normally supports built-in resources like: Deployment Service Pod ConfigMap Secret Ingress These are called native resources. Sometimes companies (Istio, ArgoCD, Prometheus Operator, Kyverno, etc.) want to add new features that Kub...
1. Why Kubernetes Services Are Needed When a Pod is created in Kubernetes, it receives a dynamic IP address.If the Pod dies and restarts, its IP changes.So other Pods (like checkout → payments) cannot rely on Pod IP because it changes, creating issue...
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.
Let’s take a simple example:
You want to containerize a Python calculator application.
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 CMD or ENTRYPOINT)
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
| 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.
To solve this problem, Docker introduced multi-stage builds.
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
FROM ubuntu AS build
RUN apt-get update && apt-get install -y python3 pip
COPY . /app
WORKDIR /app
RUN python3 setup.py build
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 excluded
Only the necessary runtime (Python + your app) remains
Image size drastically reduces
Imagine a 3-tier application:
Frontend (React)
Backend (Java Spring Boot)
Database (MySQL)
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.
| 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 🚀 |
# 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"]
AS build → Creates a named stage
COPY --from=build → Copies artifact from build stage
FROM scratch → Uses an empty minimal image (distroless base)
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
| 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) |
| 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 |
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.”
Go produces statically compiled binaries.
Doesn’t even need a runtime to execute.
Works perfectly with the scratch base image.
Final image size can be as small as 1–2 MB.
Hence, Go + Multi-Stage + Distroless = 💯 perfect combination.
Visit the official Google Distroless GitHub repository:
👉 https://github.com/GoogleContainerTools/distroless
There you’ll find folders for:
base, cc, java, python3, nodejs, etc.gcr.io/distroless/java17).| 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). |
| 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