Docker cookbook · Beginner

Build a production image for a Python web app

Package a Python API (FastAPI, Flask, Django) in a small, cache-friendly, non-root image.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Use a slim base, install dependencies from a lockfile in their own layer, then copy the code. Create a non-root user, set Python's unbuffered output, and start the server in exec form.

Solution

# syntax=docker/dockerfile:1
FROM python:3.14-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
RUN useradd --uid 10001 --no-create-home app
COPY src/ ./src/
USER 10001
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "2", "-k", "uvicorn.workers.UvicornWorker", "src.main:app"]

Pitfalls

  • Copying the source before installing dependencies, so every code edit reinstalls packages.
  • Binding the server to 127.0.0.1 inside the container.
  • Running as root because the base image does.

Variations

  • Use uv (COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv, then uv sync --frozen) for faster installs.
  • Build wheels in a builder stage when dependencies need compilers, then copy only the wheels.

Further reading: Dockerfile best practices

Reference: https://docs.docker.com/build/building/best-practices/

More Docker recipes

Was this page helpful?