WhatsApp

🐳 Docker

Docker Image Optimization — From 1.2GB to 68MB

Docker images are easy to build and easy to neglect. A naive Dockerfile produces images that are gigabytes in size, take minutes to pull, and contain build tools, package caches, and temporary files that have no place in production. This project explores Docker image optimization systematically — with real measurements showing the size reduction at each step.

Why Image Size Matters

Baseline — What an Unoptimized Image Looks Like

# Naive Dockerfile
FROM python:3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
Result: 1.23 GB Includes: full Python runtime, apt cache, pip cache, build tools, development headers, test frameworks

Optimization 1 — Slim Base Image

FROM python:3.11-slim   # replaces python:3.11
Result: 310 MB (-75%) Removes: apt cache, development headers, documentation

Optimization 2 — Multi-Stage Build

The biggest win. Build dependencies are only needed during compilation — they don't belong in the production image. Multi-stage builds let you compile in one stage and copy only the output to the final image.

# Stage 1: build
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

# Stage 2: production — no build tools
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY app.py .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Result: 148 MB (-88% from baseline) Build stage discarded entirely — only runtime artifacts copied

Optimization 3 — Alpine Base

FROM python:3.11-alpine
Result: 68 MB (-94% from baseline) Tradeoff: musl libc vs glibc — some packages behave differently. Test thoroughly before using Alpine in production.

Layer Caching — Build Speed Optimization

Docker caches each layer. If a layer hasn't changed, Docker reuses the cache. Copy dependencies before application code — dependencies change less often than app code, so the expensive pip install layer gets cached between most builds.

# Wrong order — cache busted on every code change
COPY . .
RUN pip install -r requirements.txt

# Right order — pip install cached unless requirements.txt changes
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

Results Summary

Baseline (python:3.11): 1.23 GB Slim base (python:3.11-slim): 310 MB (-75%) Multi-stage build: 148 MB (-88%) Alpine base: 68 MB (-94%)

Key Lessons

Work With Me

Need help implementing any of this?

I offer consulting for Linux, AWS, CI/CD, Docker, Terraform, and monitoring setup. Let's talk.

Book Free Consultation WhatsApp →