Phase 25 of 25 · Topic 25.1

Multi-Stage Dockerfile for Python Microservices

1Concept

A Multi-Stage Dockerfile uses a builder stage with compilers to build wheels and virtual environments, copying only the compiled artifacts into a lightweight distroless/slim runtime image, shrinking image size from 1GB to <120MB and eliminating compiler security vulnerabilities.

2Architecture Diagram

Build Stage (python:3.12-slim + gcc) ---> Builds Wheels & Virtualenv
                                                  |
                                           Copy venv ONLY
                                                  v
Final Stage (python:3.12-slim)       ---> 80MB Minimal Container Image!

3Code Example

Python 3.12
dockerfile_sample = '''
# 1. Builder Stage
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc libpq-dev
COPY requirements.txt .
RUN python -m venv /opt/venv && \
    /opt/venv/bin/pip install --no-cache-dir -r requirements.txt

# 2. Final Minimal Runtime Stage
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY src/ /app/src/
USER 10001
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
'''
print("=== Production Multi-Stage Dockerfile ===")
print(dockerfile_sample.strip())

4Expected Output

=== Production Multi-Stage Dockerfile ===
# 1. Builder Stage
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc libpq-dev
COPY requirements.txt .
RUN python -m venv /opt/venv && \
    /opt/venv/bin/pip install --no-cache-dir -r requirements.txt

# 2. Final Minimal Runtime Stage
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY src/ /app/src/
USER 10001
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

5Key Takeaways

  • Never run containers as root; specify `USER 10001`.
  • Multi-stage builds eliminate build tools (gcc, make) from production container images.
  • Use `.dockerignore` to exclude `.git`, `__pycache__`, and local `.venv`.