Building Optimized, Minimal Container Images

Minimizing container image sizes produces faster Kubernetes startup times, lowers network transfer and storage costs, speeds up CI/CD pipelines, and significantly reduces the container's security attack surface by stripping out unnecessary binaries, package managers, and shells.
Key Optimization Strategies
1. Multi-Stage Builds (The Builder Pattern)
Multi-stage builds allow you to compile code inside a heavyweight build environment and copy only the compiled binary or runtime assets into a lean, minimal final image.
# Stage 1: Build & Compile
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /bin/app .
# Stage 2: Final Minimal Runtime
FROM gcr.io/distroless/static-debian12:nonroot
WORKDIR /app
COPY --from=builder /bin/app /app/app
USER nonroot:nonroot
ENTRYPOINT ["/app/app"]
2. Distroless and Alpine Base Images
| Base Image Type | Typical Size | Includes Shell / Package Manager | Best For |
|---|---|---|---|
gcr.io/distroless/static |
~2 MB | ❌ No | Statically compiled Go / Rust binaries |
alpine:latest |
~7 MB | ✅ Yes (ash, apk) |
General utilities, Python, Node.js |
python:3.12-slim |
~120 MB | ✅ Yes (bash, apt) |
Complex Python apps with C dependencies |
ubuntu:latest |
~75 MB | ✅ Yes (bash, apt) |
Development / Legacy monoliths |
3. Layer Caching & Instruction Order
Docker caches each instruction layer independently. Place slowly changing instructions (like installing OS dependencies and downloading package modules) before frequently changing source code:
FROM python:3.12-slim
WORKDIR /app
# 1. Install system dependencies first
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
# 2. Copy requirements and install python packages (cached across code edits)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 3. Copy application code last
COPY . .
CMD ["python", "main.py"]
4. Leverage .dockerignore
Prevent committing large, sensitive, or redundant build artifacts into the build context:
.dockerignore
Image Inspection Tools
- Dive: Interactive terminal UI to explore layer contents and discover wasted space.
- Docker Slim (SlimToolkit): Automatically inspects and minifies container images dynamically.
- Docker BuildKit Squash: Merge intermediate layers into a single clean layer (
docker build --squash).