Distroless Docker Images


Introduction
If you’ve ever run docker images
and noticed your image is huge, or wondered why you're shipping a full OS with your app, you’re not alone. That’s where distroless images come in — a clean, secure, and efficient way to package applications with Docker.
In this guide, we’ll cover:
What are distroless images?
Why they matter
How they differ from Alpine and scratch
Pros and cons
Real-life use cases
Step-by-step examples
What Are Distroless Docker Images?
Distroless images are Docker images without a base operating system like Ubuntu or Alpine. They contain only the application and its runtime dependencies — nothing more.
That means:
✅ No package managers
✅ No shell (sh
, bash
)
✅ No debugging tools
✅ Just your app and what it strictly needs to run
These images are maintained by Google and are designed for production environments where security, size, and simplicity matter most.
Why Use Distroless Images?
Let’s say you build a Python or Node.js app. With a traditional image (like Ubuntu), your app may carry:
apt package manager
curl, wget, nano, etc.
Extra libraries you don’t even use
But with distroless
, your image carries only your app and Python/Node.js runtime. That’s it.
🔐 Benefits of Distroless:
Feature | Benefit |
Smaller size | Faster downloads and deployments |
More secure | Fewer attack vectors (no shell or package manager) |
Production ready | Clean and minimal for stable environments |
Better caching | Smaller layers = better Docker layer reuse |
⚖️ Distroless vs Alpine vs Scratch
Feature | Alpine | Scratch | Distroless |
OS Base | Yes (minimal) | No | No |
Shell | Yes (sh ) | No | No |
Debuggable | Somewhat | No | Harder |
Use Case | Dev & Prod | Special cases | Secure Production |
Real-Life Example: Python App
Let’s build and compare a Dockerfile using Ubuntu vs. Distroless.
Traditional Ubuntu-based Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]
Typical size: 150MB+
Distroless Dockerfile
# Build Stage
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --target=/app/packages -r requirements.txt
COPY . .
# Final Stage - Distroless
FROM gcr.io/distroless/python3
WORKDIR /app
COPY --from=builder /app /app
CMD ["python3", "main.py"]
🔍 Size: 40MB–60MB
🔒 Security: No shell, no package manager
⚡ Performance: Lightning fast startup
When to Use Distroless (and When Not To)
✅ Perfect for:
Microservices
CI/CD pipelines
Final production builds
Security-sensitive environments
❌ Avoid if:
You need to debug with shell access
You’re still experimenting or setting up
Your app needs dynamic OS dependencies
👉 A common approach is:
Use
python:3.11-slim
for development, and switch togcr.io/distroless/python3
for production builds.
Tips When Working With Distroless
No shell access
You can’t just
docker exec -it my-container bash
Debug using logs or temporarily switch to Alpine in dev
Multi-stage builds are your friend
- Compile and bundle everything in one stage, copy minimal output to final stage
Static Binaries work great
- Go, Rust, Java apps shine in distroless
Pro Tip: Inspect Distroless Images
Want to inspect what’s inside a distroless image?
Use Dive Command:
dive gcr.io/distroless/python3
Or you can also extract with:
docker run --rm -it --entrypoint sh gcr.io/distroless/base
Just don’t expect to see a shell 😄
Wrapping Up
Distroless images are a superpower for modern Docker users who care about security, size, and performance.
While they may not be perfect for every use case, they’re an incredible choice for production-ready applications.
Subscribe to my newsletter
Read articles from Anuj Kumar Upadhyay directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Anuj Kumar Upadhyay
Anuj Kumar Upadhyay
I am a developer from India. I am passionate to contribute to the tech community through my writing. Currently i am in my Graduation in Computer Application.