Python with uv
Best practices for Dockerfile for Python with uv
π³ Annotated Dockerfile for Python with uv:
# Use a slim and modern base image: Python 3.12 on Debian Bookworm
FROM python:3.12-slim-bookworm AS base
# --------------------------------------
# Stage 1: Builder - installs dependencies and prepares environment
# --------------------------------------
FROM base AS builder
# Copy pre-built uv binary from official image
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv
# Enable uv optimizations:
# UV_COMPILE_BYTECODE=1 compiles Python bytecode for faster startup
# UV_LINK_MODE=copy ensures dependencies are copied (isolated env)
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
# Set the working directory in container to /app
WORKDIR /app
# Copy dependency files
COPY pyproject.toml uv.lock /app/
# Create a virtual environment first
RUN uv venv
# Install dependencies from the lock file
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install -r uv.lock --no-deps
# Now copy the source code
COPY . /app
# Install your project itself
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install -e .
# --------------------------------------
# Stage 2: Final production image - minimal and optimized
# --------------------------------------
FROM base
# Copy prepared app environment from builder stage
COPY --from=builder /app /app
# Add virtual environment bin folder to PATH for easy command access
ENV PATH="/app/.venv/bin:$PATH"
# Expose port 8000 for application server
EXPOSE 8000
# Default command to start your Python app
CMD ["python", "app.py"]
π Why these are best practices
β Slim Base Images (python:3.12-slim-bookworm)
- Minimizes image size, enhancing security and reducing container startup time.
- Debian Bookworm provides modern dependencies with stable long-term support.
β Using uv (Ultra-fast Python package manager)
- Faster and more efficient than traditional pip.
- Built-in dependency caching significantly improves build speeds.
- Ensures reproducible builds through lock files (uv.lock), avoiding dependency drift.
β Multi-stage Builds
- Keeps final image minimal by excluding build-time artifacts (e.g., cache files, temporary dependencies).
- Reduces production container size, resulting in lower resource usage and faster deployments.
β Dependency and Source Separation
- Copying dependency-related files separately allows Docker to reuse cached layers effectively.
- Changes in source code donβt trigger unnecessary reinstallations of unchanged dependencies.
β Mounting Cache (--mount=type=cache)
- Dramatically reduces build time in CI/CD environments by reusing cached downloads and installed packages.
β Environment Variables
- UV_COMPILE_BYTECODE=1 compiles bytecode, which optimizes startup times in production.
- UV_LINK_MODE=copy isolates dependencies clearly, simplifying management and ensuring immutability.
π Additional best practices to consider
Run as a Non-root User
For enhanced security, switch to a non-root user in your production container.
FROM base
RUN useradd -m appuser
COPY --from=builder /app /app
ENV PATH="/app/.venv/bin:$PATH"
WORKDIR /app
USER appuser
EXPOSE 8000
CMD ["uvicorn", "uv_docker_example:app", "--host", "0.0.0.0", "--port", "8000"]
Add Health Checks
Integrate Dockerβs built-in health monitoring to enable auto-recovery mechanisms.
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8000/health || exit 1
(This requires adding a /health endpoint to your Python app.)
Use .dockerignore file
Avoid accidentally copying unwanted files (e.g., logs, .git, test folders):
.venv
__pycache__
*.pyc
.git
tests/
docker-compose.yml
Explicit Resource Limits
Set CPU and memory limits explicitly when running containers (via Kubernetes, Docker Compose, or runtime flags).
Example (Docker Compose):
services:
web:
build: .
deploy:
resources:
limits:
cpus: "1.0"
memory: "512M"
By following these annotations and additional best practices, youβll achieve containers that are fast to build, secure, easy to maintain, and optimized for production environments.
Last updated on