1. Choose the Right Base Image#
1
2
3
4
5
6
7
8
9
10
|
# ❌ Too large
FROM ubuntu:22.04 # ~77MB
FROM python:3.11 # ~1GB
# ✅ Recommended
FROM python:3.11-alpine # ~50MB
FROM python:3.11-slim # ~130MB
# ✅ Smallest
FROM gcr.io/distroless/python3 # ~20MB
|
| Base image |
Size |
ubuntu:22.04 |
~77MB |
python:3.11 |
~1GB |
python:3.11-alpine |
~50MB |
distroless |
~20MB |
2. Use Multi-Stage Builds#
The most effective technique: compile in a large image, ship the artifact from a minimal one.
1
2
3
4
5
6
7
8
9
10
11
|
# Stage 1: compile
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# Stage 2: runtime
FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]
|
A Go app goes from ~1GB to ~15MB.
3. Combine RUN Instructions#
1
2
3
4
5
6
7
8
9
10
11
12
|
# ❌ Multiple layers
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y wget
RUN rm -rf /var/lib/apt/lists/*
# ✅ Combined into one layer
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
wget && \
rm -rf /var/lib/apt/lists/*
|
4. Clean Up Build Cache#
1
2
3
4
5
6
7
8
9
|
# Python — disable pip cache
RUN pip install --no-cache-dir -r requirements.txt
# Node.js — clear npm cache
RUN npm ci --only=production && \
npm cache clean --force
# Go — strip debug info
RUN go build -ldflags="-s -w" -o myapp
|
5. Use .dockerignore#
1
2
3
4
5
6
7
8
9
10
11
|
# .dockerignore
.git
node_modules
*.md
.env
.vscode
__pycache__
*.pyc
dist
build
coverage
|
1
2
|
# Check context size
docker build --no-cache -t test . 2>&1 | grep "Sending build context"
|
6. Install Only What You Need#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# ❌ Build tools left in the runtime image
FROM ubuntu:22.04
RUN apt-get install -y build-essential gcc make cmake
COPY . .
RUN make && make install
CMD ["./myapp"]
# ✅ Build and runtime separated
FROM ubuntu:22.04 AS builder
RUN apt-get install -y build-essential gcc make
COPY . .
RUN make && make install
FROM ubuntu:22.04
COPY --from=builder /app/myapp .
CMD ["./myapp"]
|
7. Use –no-install-recommends#
1
2
3
4
5
|
# ❌ Installs all recommended packages
RUN apt-get install -y curl
# ✅ Install only what's required (~50% fewer dependencies)
RUN apt-get install -y --no-install-recommends curl
|
8. Compress Static Assets#
1
2
3
4
5
6
7
8
9
10
11
|
# Minify JavaScript
RUN uglifyjs app.js -o app.min.js
# Minify CSS
RUN cssnano app.css app.min.css
# Optimize images
RUN find . -name "*.png" -exec optipng {} \;
# Strip debug info from Go binaries
RUN go build -ldflags="-s -w" -o myapp
|
9. Use Squash to Merge Layers#
1
2
|
# Merge all layers into one, removing duplicate files from intermediate layers
docker build --squash -t myapp:slim .
|
Requires the experimental feature to be enabled in /etc/docker/daemon.json.
10. Analyze Image Layers#
1
2
3
4
5
6
7
|
# Use dive to analyze each layer's size and content
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive myapp:latest
# Or use docker history
docker history myapp:latest
|
Real-World Case: Python App#
1
2
3
4
5
6
|
# ❌ Before optimization (1.2GB)
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
|
1
2
3
4
5
6
7
8
9
10
11
12
|
# ✅ After optimization (150MB, 87% smaller)
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
|
Real-World Case: Node.js App#
1
2
3
4
5
6
|
# ❌ Before optimization (1.1GB)
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
|
1
2
3
4
5
6
7
8
9
10
11
12
|
# ✅ After optimization (180MB, 84% smaller)
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
USER node
CMD ["node", "server.js"]
|
| Tool |
Purpose |
dive |
Analyze each layer’s content and size |
docker-slim |
Automatically shrink images |
hadolint |
Dockerfile static analysis |
trivy |
Container security scanning |