๐ Distroless & Multi-Stage Docker Images: Building Production-Ready Containers


When deploying applications to production, container image optimization is a critical step. Large, bloated images not only increase build and deployment time but also expose your application to unnecessary security vulnerabilities. This is where multi-stage builds and distroless images come in.
๐น What is a Multi-Stage Docker Image?
A multi-stage Docker build is a way to create leaner Docker images by separating the build environment from the runtime environment.
In the builder stage, you install dependencies, compile code, and prepare artifacts.
In the final stage, you copy only the necessary files into a smaller base image, leaving behind build tools, caches, and unnecessary libraries.
โ This results in a smaller, faster, and more secure image.
๐น What is a Distroless Image?
A distroless image is a minimal container image that does not contain a full operating system (like Debian, Ubuntu, or Alpine).
It only contains:
Your application binaries
Language runtime (Python, Node.js, Java, etc.)
Minimal libraries required to run the app
๐ Thereโs no shell (/bin/bash
), package manager (apt
, yum
), or extra utilities.
โ Why? Because in production, your app doesnโt need them โ they only increase attack surface and image size.
Google maintains Distroless images for many languages, widely used in production.
๐น Why Use Multi-Stage + Distroless for Production?
Smaller images โ Faster build, push, and deploy times.
Reduced attack surface โ No unnecessary tools for attackers to exploit.
Improved security โ Fewer CVEs (common vulnerabilities & exposures).
Best practice for production โ Industry-standard for Kubernetes & cloud environments.
๐น Example: Multi-Stage Build with Distroless (Python Flask App)
Hereโs a sample Dockerfile using multi-stage builds + distroless:
#Stage : 1
From python:3.9-slim AS builder #Base image (OS)
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt --target=/app/deps
#requirements.txt dependancy file
#Stage : 2
FROM gcr.io/distroless/python3-debian12
WORKDIR /app
COPY --from=builder /app/deps /app/deps
COPY --from=builder /app .
ENV PYTHONPATH="/app/deps"
EXPOSE 80
CMD ["run.py"]
๐น Explanation of Each Stage
Stage 1: Builder
FROM python:3.9-slim
โ Use a lightweight Python image with build tools.Install dependencies with
pip install
.Copy project files into
/app
.This stage contains build tools (pip, compilers), but they wonโt go into the final image.
Stage 2: Distroless Runtime
FROM gcr.io/distroless/python3.12
โ Pulls a minimal runtime-only Python image.Copy only whatโs needed: app code + dependencies from builder stage.
Set
ENV PATH
so installed dependencies are available.Run the app with
CMD ["run.py"]
.
It shows how image sizes reduce as you move from a full OS image โ slim โ multi-stage โ distroless.
Fat Image (Full OS): ~800 MB
Slim Image: ~300 MB
Multi-Stage: ~150 MB
Distroless: ~60 MB
๐น Key Takeaways
Multi-stage builds โ Separate build & runtime, reduce size.
Distroless images โ Strip OS packages, making images more secure.
Production-ready โ Smaller attack surface, faster deployments, best practice for Kubernetes.
๐ If youโre shipping containers to production, always consider multi-stage builds with distroless images. Theyโll keep your deployments fast, secure, and efficient.
#Docker
#Distroless
#Productionready
Subscribe to my newsletter
Read articles from Pratik Prajapati directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Pratik Prajapati
Pratik Prajapati
๐ Welcome to my Hashnode blog! I'm a Web developer with 7 year's of experience and now I am going to change my domain as DevOps Engineer with lots of hands on experience.