Skip to main content
uv provides official Docker images and integrates seamlessly with Docker workflows for Python dependency management. This guide covers best practices for using uv in Docker to optimize build times and image sizes.

Available Images

uv provides both distroless images (containing only uv binaries) and derived images (based on popular base images with uv pre-installed).

Distroless Images

# Latest version
FROM ghcr.io/astral-sh/uv:latest

# Specific version (recommended)
FROM ghcr.io/astral-sh/uv:0.10.8

# Major.minor version
FROM ghcr.io/astral-sh/uv:0.10

Derived Images

# Alpine-based
FROM ghcr.io/astral-sh/uv:alpine
FROM ghcr.io/astral-sh/uv:python3.12-alpine

# Debian-based
FROM ghcr.io/astral-sh/uv:debian-slim
FROM ghcr.io/astral-sh/uv:python3.12-trixie-slim

Installing uv

1

Copy from distroless image

The recommended approach is to copy the uv binary from the official distroless image:
FROM python:3.12-slim-trixie
COPY --from=ghcr.io/astral-sh/uv:0.10.8 /uv /uvx /bin/
For reproducible builds, pin to a specific SHA256:
COPY --from=ghcr.io/astral-sh/uv@sha256:2381d6aa60c326b71fd40023f921a0a3b8f91b14d5db6b90402e65a635053709 /uv /uvx /bin/
2

Alternative: Use installer

You can also use the installer script:
FROM python:3.12-slim-trixie

# Install curl for the installer
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates

# Download and run installer
ADD https://astral.sh/uv/0.10.8/install.sh /uv-installer.sh
RUN sh /uv-installer.sh && rm /uv-installer.sh

# Add to PATH
ENV PATH="/root/.local/bin/:$PATH"

Basic Project Setup

1

Install uv and copy project

FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Copy the project into the image
COPY . /app
WORKDIR /app
Add .venv to your .dockerignore file to prevent including the local virtual environment in the image.
2

Sync dependencies

# Disable development dependencies
ENV UV_NO_DEV=1

# Sync the project
RUN uv sync --locked
3

Set up the entrypoint

# Option 1: Use uv run
CMD ["uv", "run", "my_app"]

# Option 2: Activate the virtual environment
ENV PATH="/app/.venv/bin:$PATH"
CMD ["my_app"]

Multi-Stage Build with Intermediate Layers

Optimize build times by separating dependency installation from project installation:
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

# Install dependencies only (separate layer for caching)
RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    uv sync --locked --no-install-project

# Copy the project and install it
COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --locked

CMD ["uv", "run", "my_app"]

For Workspaces

When using workspaces, use --frozen and --no-install-workspace:
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    uv sync --frozen --no-install-workspace

COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --locked

Production Optimization

Non-Editable Multi-Stage Build

Create smaller production images by excluding source code:
# Build stage
FROM python:3.12-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

# Install dependencies
RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    uv sync --locked --no-install-project --no-editable

# Copy and install project
COPY . /app
RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --locked --no-editable

# Production stage
FROM python:3.12-slim

# Copy only the virtual environment
COPY --from=builder --chown=app:app /app/.venv /app/.venv

# Run the application
CMD ["/app/.venv/bin/hello"]

Compile Bytecode

Improve startup time by compiling Python bytecode:
# Set globally
ENV UV_COMPILE_BYTECODE=1

RUN uv python install
RUN uv sync

# Or use flags
RUN uv python install --compile-bytecode
RUN uv sync --compile-bytecode

Caching

Use cache mounts to speed up builds:
ENV UV_LINK_MODE=copy

RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync
For managed Python installations:
ENV UV_PYTHON_CACHE_DIR=/root/.cache/uv/python

RUN --mount=type=cache,target=/root/.cache/uv \
    uv python install

Development Setup

Using docker run

Mount your project while preserving the container’s virtual environment:
docker run --rm \
  --volume .:/app \
  --volume /app/.venv \
  my-image

Using Docker Compose with Watch

services:
  example:
    build: .
    develop:
      watch:
        # Sync working directory
        - action: sync
          path: .
          target: /app
          ignore:
            - .venv/

        # Rebuild on config changes
        - action: rebuild
          path: ./pyproject.toml
Run with:
docker compose watch

Using uv pip

1

Enable system Python

ENV UV_SYSTEM_PYTHON=1
2

Install packages

RUN uv pip install --system ruff
3

Install from requirements

COPY requirements.txt .
RUN uv pip install -r requirements.txt

Installing Tools

Make installed tools available in the PATH:
ENV PATH=/root/.local/bin:$PATH
RUN uv tool install cowsay

# Or set a custom location
ENV UV_TOOL_BIN_DIR=/opt/uv-bin/

Verifying Image Provenance

Verify official uv images using GitHub attestations:
# Using GitHub CLI
gh attestation verify --owner astral-sh oci://ghcr.io/astral-sh/uv:0.10.8

# Using cosign
REPO=astral-sh/uv
gh attestation download --repo $REPO oci://ghcr.io/${REPO}:0.10.8
docker buildx imagetools inspect ghcr.io/${REPO}:0.10.8 --format "{{json .Manifest}}" > manifest.json
cosign verify-blob-attestation \
  --new-bundle-format \
  --bundle "$(jq -r .digest manifest.json).jsonl" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  --certificate-identity-regexp="^https://github\.com/${REPO}/.*" \
  <(jq -j '.|del(.digest,.size)' manifest.json)

Complete Example

See the uv-docker-example repository for a complete working example demonstrating best practices.

Build docs developers (and LLMs) love