๐Ÿš€ 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

0
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.