Optimizing Dockerfiles for Layers
LEVEL 0
The Problem
Your image is 2GB. Builds take forever. Container registry bills are high. You suspect your Dockerfile could be better.
LEVEL 1
The Concept — Minimizing Layers, Maximizing Efficiency
The Concept
Think about moving to a new apartment.
Inefficient: Take 50 trips with small boxes, leaving packing material everywhere, bringing stuff you don’t need.
Efficient: Pack strategically, consolidate, leave behind what you don’t need, clean as you go.
Dockerfile optimization is similar: combine operations, clean up in the same layer, don’t include unnecessary files.
LEVEL 2
The Mechanics — Optimization Techniques
The Mechanics
1. Combine RUN Commands
Bad (3 layers, cleanup doesn’t help):
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
Good (1 layer, cleanup works):
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
2. Clean Up in the Same Layer
Once a file is in a layer, it’s there forever — even if you delete it in a later layer. The delete just creates a whiteout; the space is still used.
Bad:
RUN wget huge-file.tar.gz
RUN tar xzf huge-file.tar.gz
RUN rm huge-file.tar.gz # Still in previous layer!
Good:
RUN wget huge-file.tar.gz && \
tar xzf huge-file.tar.gz && \
rm huge-file.tar.gz
3. Use Specific COPY
Bad:
COPY . . # Includes everything, invalidates often
Good:
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./src/
COPY config/ ./config/
4. Order Layers by Change Frequency
# Rarely changes
FROM python:3.11-slim
RUN apt-get update && apt-get install -y ...
# Sometimes changes
COPY requirements.txt .
RUN pip install -r requirements.txt
# Frequently changes
COPY . .
CMD ["python", "app.py"]
5. Use Slim/Alpine Base Images
# 1.01 GB
FROM python:3.11
# 131 MB
FROM python:3.11-slim
# 51 MB (but may have compatibility issues)
FROM python:3.11-alpine
LEVEL 3
Measuring Impact
# See layer sizes
docker history myapp
# See total size
docker images myapp
# Detailed size breakdown
docker inspect myapp --format '{{.Size}}'
LEVEL 4