📖 Original Reference: Originally published with performance benchmarks and deployment pipelines at alexmaina.dev/python-uv-github-actions.
In standard Python CI/CD pipelines, pip install or poetry install is notoriously slow, burning 2 to 5 billable minutes on every commit just resolving wheel dependencies.
uv, created in Rust by Astral (the authors of Ruff), is an extremely fast Python package and project manager designed as a drop-in replacement for Pip, Pip-tools, Virtualenv, and Poetry.
Here is how to migrate an existing project, lock dependencies with uv.lock, and reduce your GitHub Actions workflow times from minutes to seconds.
1. Quick Migration Commands
# Install uv (Linux/macOS)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install uv (Windows PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Initialize standard PEP 621 project
uv init my-project
cd my-project
# Add dependencies with automatic lockfile update
uv add fastapi uvicorn "pydantic>=2.0"
uv add --dev pytest ruff
# Run tests instantly in isolated environment
uv run pytest
2. Optimized GitHub Actions Workflow
In .github/workflows/ci.yml, leverage the official astral-sh/setup-uv action with built-in cache keying:
name: Test & Lint Python
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup uv with automatic dependency caching
uses: astral-sh/setup-uv@v5
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install required Python version
run: uv python install 3.12
- name: Sync dependencies from lockfile
run: uv sync --frozen --all-extras --dev
- name: Lint with Ruff
run: uv run ruff check .
- name: Run Pytest
run: uv run pytest --maxfail=1 -q
3. Production Multi-Stage Dockerfile
Use uv during the build stage to compile wheels and copy strictly the finalized .venv into the production runtime container:
# STAGE 1: Dependency resolution & build
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS builder
WORKDIR /app
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project
COPY . .
RUN uv sync --frozen --no-dev
# STAGE 2: Minimal runtime image
FROM python:3.12-slim-bookworm
WORKDIR /app
COPY --from=builder /app/.venv /app/.venv
COPY . /app
ENV PATH="/app/.venv/bin:$PATH"
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Author: Alessandro Mainardi — Software Developer & Computer Engineering Student @ UniBo. Explore modern tooling and software engineering guides at alexmaina.dev.
Top comments (0)