Slim base and uv
A naive Dockerfile bakes the build toolchain, tests, and cached wheels into the final image. You ship 1.2 GB, pull times are painful, and the attack surface is huge. A multi-stage build splits dependency resolution from runtime so the final image only carries what the app actually needs to run.
# syntax=docker/dockerfile:1.7
# ---------- Stage 1: builder ----------
FROM python:3.11-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
ENV UV_LINK_MODE=copy \
UV_PROJECT_ENVIRONMENT=/app/.venv
COPY pyproject.toml ./
RUN uv sync --no-devThe builder stage pulls uv from its official image and resolves the project dependencies into a self-contained .venv at /app/.venv. Skipping dev dependencies keeps the virtualenv to what the app actually needs at runtime.
Two stages, one image
Everything heavy stays in the builder. Only the venv and code land in runtime.
Quiz: Quiz
Loading practice…