Modern UV Package Management Guide¶
A comprehensive guide for using UV (version 0.8.22+) as the modern Python package manager in Dashtam, covering installation, workflows, Docker integration, and best practices.
Overview¶
UV is an extremely fast Python package manager and resolver, written in Rust. It's designed as a drop-in replacement for pip, pip-tools, poetry, and other Python package management tools.
What You'll Learn¶
- How to install and configure UV in Docker and on host machines
- Modern Python dependency management with UV project mode
- Adding, removing, and upgrading dependencies
- Syncing environments after pulling changes
- Docker integration with official UV images
- Migrating from pip or poetry to UV
- Troubleshooting common UV issues
When to Use This Guide¶
Use this guide when:
- Setting up Dashtam development environment
- Adding new Python dependencies to the project
- Updating existing dependencies
- Troubleshooting dependency installation issues
- Migrating from pip or poetry
- Optimizing Docker builds with UV
Why UV¶
- 10-100x faster than pip for package installation
- Deterministic resolution with lockfiles (reproducible builds)
- Modern Python workflow following PEP 621 standards
- Docker-optimized with official container images
- Universal resolver handles complex dependency scenarios
- No separate tools needed (replaces pip, poetry, pipenv)
Core Concepts¶
UV distinguishes between two modes:
Project Management Mode (Modern - Dashtam uses this):
- Uses
uv add,uv sync,uv lockcommands - Manages dependencies in
pyproject.tomlanduv.lock - Creates and manages virtual environments automatically
- For applications with modern Python project structure
Package Management Mode (Legacy):
- Uses
uv pipcommands (pip-compatible interface) - For one-off package installations
- Compatible with
requirements.txt - Use only when absolutely necessary for legacy compatibility
Prerequisites¶
Before using this guide, ensure you have:
- Docker Desktop installed (for containerized development)
- Basic understanding of Python package management
- Access to Dashtam repository
- Terminal access to development environment
Required Tools:
- Docker Desktop - Latest version (for containerized UV)
- Python 3.13 - Required version for Dashtam
- UV 0.8.22+ - Latest version recommended
Required Knowledge:
- Basic command line usage
- Understanding of Python virtual environments
- Familiarity with dependency management concepts
- Basic Docker commands
Step-by-Step Instructions¶
Step 1: Install UV¶
Choose installation method based on your environment.
In Docker (Recommended for Dashtam):
# Use official UV image with Python 3.13
FROM ghcr.io/astral-sh/uv:0.8.22-python3.13-trixie-slim AS base
# Set UV environment variables
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_PROJECT_ENVIRONMENT=/app/.venv \
PATH="/app/.venv/bin:$PATH"
On Host Machine (macOS):
# Via Homebrew (recommended)
brew install uv
# Via curl
curl -LsSf https://astral.sh/uv/install.sh | sh
# Verify installation
uv --version
What This Does:
- Downloads and installs UV binary
- Sets up UV in system PATH
- Enables modern Python package management
Step 2: Initialize Project¶
Initialize UV project structure for new or existing projects.
For New Projects:
# Create new project with pyproject.toml
uv init --app --name myproject --python 3.13
# What gets created:
# - pyproject.toml (project configuration)
# - .python-version (Python version pinning)
# - src/myproject/ (source directory)
For Existing Projects (Like Dashtam):
# Initialize in existing directory
uv init --app --name dashtam --python 3.13 --no-readme
# Add existing dependencies from requirements.txt
uv add --requirements requirements.txt
uv add --dev --requirements requirements-dev.txt
Important Notes:
--appflag indicates application (not a library)--python 3.13sets Python version requirement--no-readmeskips README.md creation if already exists
Step 3: Manage Dependencies¶
Add, remove, and update project dependencies.
Adding Production Dependencies:
# Add latest version
uv add boto3
# Add specific version
uv add "boto3==1.40.45"
# Add with version constraints
uv add "boto3>=1.40.0,<2.0.0"
# Add multiple packages
uv add boto3 requests httpx
# Add from requirements.txt
uv add --requirements requirements.txt
Adding Development Dependencies:
# Add dev tools
uv add --dev pytest pytest-cov ruff
# Add from requirements-dev.txt
uv add --dev --requirements requirements-dev.txt
Removing Dependencies:
# Remove package
uv remove boto3
# Remove multiple packages
uv remove boto3 requests
# Remove dev dependency
uv remove --dev pytest
What Happens When Adding:
- UV resolves all dependencies
- Updates
pyproject.tomlwith new dependency - Updates
uv.lockwith exact resolved versions - Installs package into
.venvimmediately - Compiles bytecode for faster imports
Step 4: Sync Environment¶
Keep your environment synchronized with project dependencies.
Basic Sync:
# Sync with lockfile (install/update/remove as needed)
uv sync
# Sync only production dependencies
uv sync --no-dev
# Force reinstall all packages
uv sync --reinstall
When to Sync:
- After pulling changes from git
- After switching branches with different dependencies
- After manually editing
pyproject.toml - When virtual environment seems corrupted
- After team member updates dependencies
Step 5: Run Commands¶
Execute Python scripts and commands with project dependencies.
Running Scripts:
# Run Python script
uv run python script.py
# Run module
uv run -m pytest
# Run installed CLI tool
uv run uvicorn src.main:app --reload
# Run with specific Python version
uv run --python 3.13 python script.py
Benefits of uv run:
- Ensures correct virtual environment is active
- No manual venv activation needed
- Consistent across all environments
- Works in CI/CD without modifications
Step 6: Integrate with Docker¶
Configure Docker to use UV for fast, deterministic builds.
Basic Docker Configuration:
# Use official UV image
FROM ghcr.io/astral-sh/uv:0.8.22-python3.13-trixie-slim AS base
# Set UV environment
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_PROJECT_ENVIRONMENT=/app/.venv \
PATH="/app/.venv/bin:$PATH"
WORKDIR /app
# Copy project files (lockfile first for caching)
COPY pyproject.toml uv.lock ./
# Sync dependencies
RUN uv sync --no-dev
# Copy application code
COPY . .
# Run application
CMD ["uv", "run", "uvicorn", "src.main:app", "--host", "0.0.0.0"]
Layer Caching Optimization:
# Good: Copy lockfile first
COPY pyproject.toml uv.lock ./
RUN uv sync --no-dev
COPY . .
# Bad: Invalidates cache on any code change
COPY . .
RUN uv sync --no-dev
Examples¶
Example 1: Adding New Dependency in Dashtam¶
Complete workflow for adding a new package in containerized development.
Scenario: Add boto3 for AWS SES integration
# 1. Add package in Docker container
docker compose -f compose/docker-compose.dev.yml exec app uv add boto3
# 2. Verify installation
docker compose -f compose/docker-compose.dev.yml exec app \
python -c "import boto3; print(boto3.__version__)"
# 3. Check what was updated
git status
# Shows: pyproject.toml and uv.lock modified
# 4. Commit changes
git add pyproject.toml uv.lock
git commit -m "feat(deps): add boto3 for AWS SES integration"
What Gets Updated:
pyproject.toml: Addsboto3>=1.40.0to dependenciesuv.lock: Locks boto3 and all its dependencies with exact versions.venv/: Package installed immediately
Example 2: After Pulling Changes¶
Sync your environment after teammate adds dependencies.
Scenario: Pull branch with new dependencies
# 1. Pull changes
git pull origin feature/new-dependencies
# 2. Check what changed
git diff HEAD@{1} -- pyproject.toml uv.lock
# 3. Sync environment
docker compose -f compose/docker-compose.dev.yml exec app uv sync
# 4. Verify everything works
docker compose -f compose/docker-compose.dev.yml exec app uv run pytest
Expected Output:
Example 3: Upgrading Dependencies¶
Update packages to latest compatible versions.
Scenario: Update FastAPI to latest version
# 1. Update specific package
docker compose -f compose/docker-compose.dev.yml exec app \
uv lock --upgrade-package fastapi
# 2. Apply updates
docker compose -f compose/docker-compose.dev.yml exec app uv sync
# 3. Test application
docker compose -f compose/docker-compose.dev.yml exec app uv run pytest
# 4. If tests pass, commit
git add uv.lock
git commit -m "chore(deps): upgrade fastapi to latest version"
Update All Packages:
# Update all to latest compatible versions
docker compose -f compose/docker-compose.dev.yml exec app \
uv lock --upgrade
docker compose -f compose/docker-compose.dev.yml exec app uv sync
Example 4: Docker Multi-Stage Build¶
Optimize Docker image size with multi-stage builds.
Complete Multi-Stage Dockerfile:
# syntax=docker/dockerfile:1
# Base stage with UV
FROM ghcr.io/astral-sh/uv:0.8.22-python3.13-trixie-slim AS base
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy
# Builder stage
FROM base AS builder
WORKDIR /app
# Copy dependency files
COPY pyproject.toml uv.lock ./
# Install production dependencies only
RUN uv sync --no-dev --frozen
# Production stage
FROM python:3.13-slim AS production
# Create non-root user
RUN useradd -m -u 1000 appuser
WORKDIR /app
# Copy virtual environment from builder
COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv
# Copy application code
COPY --chown=appuser:appuser . .
# Set PATH to use venv
ENV PATH="/app/.venv/bin:$PATH"
USER appuser
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
Result: Production image ~200MB smaller than development image.
Example 5: Migration from pip¶
Migrate existing pip-based project to UV.
Scenario: Convert Dashtam from pip to UV
# 1. Initialize UV project
uv init --app --name dashtam --python 3.13
# 2. Add all dependencies
uv add --requirements requirements.txt
uv add --dev --requirements requirements-dev.txt
# 3. Verify lockfile created
ls -la uv.lock
# 4. Test in clean environment
docker compose -f compose/docker-compose.test.yml up --build
# 5. If successful, commit UV files
git add pyproject.toml uv.lock
git commit -m "build: migrate from pip to UV package management"
# 6. (Optional) Keep requirements.txt for compatibility
uv pip compile pyproject.toml -o requirements.txt
Verification¶
Check 1: UV Installation¶
Verify UV is properly installed and accessible.
# Check UV version
uv --version
# Expected: uv 0.8.22 or higher
# Check UV in Docker
docker compose -f compose/docker-compose.dev.yml exec app uv --version
# Check UV configuration
uv config list
Expected Result: UV version displays without errors.
Check 2: Dependencies Installed¶
Verify all dependencies are properly installed.
# Show dependency tree
uv tree
# Check specific package
uv tree --package fastapi
# List installed packages
uv pip list
# In Docker
docker compose -f compose/docker-compose.dev.yml exec app uv tree
Expected Result: All dependencies listed with correct versions.
Check 3: Environment Synced¶
Verify environment matches lockfile.
# Validate lockfile
uv lock --check
# Show what would change (dry run)
uv sync --dry-run
# Verify by running tests
uv run pytest
Expected Result: "Environment is already synced" or tests pass successfully.
Troubleshooting¶
Issue 1: No module named package¶
Symptoms:
- ImportError when running Python code
- Module not found errors in tests
- Application crashes on import
Cause: Package not installed or virtual environment not synced.
Solution:
# Sync environment with lockfile
uv sync
# Or add package if genuinely missing
uv add package-name
# Force reinstall if corrupted
uv sync --reinstall
Issue 2: uv command not found¶
Symptoms:
- "uv: command not found" error
- Commands fail in Docker container
- UV not available in PATH
Cause: UV not installed or not in PATH.
Solution:
# Check if UV exists in Docker
docker compose -f compose/docker-compose.dev.yml exec app which uv
# If missing, rebuild container
docker compose -f compose/docker-compose.dev.yml build --no-cache
# On host machine, reinstall UV
brew install uv # macOS
curl -LsSf https://astral.sh/uv/install.sh | sh # Linux/Unix
Issue 3: Environment Out of Sync¶
Symptoms:
- Different versions than expected
- Import errors after pulling changes
- Lockfile and installed packages mismatch
Cause: Environment not synced after lockfile changes.
Solution:
# Force re-sync
uv sync --reinstall
# Or recreate virtual environment
rm -rf .venv
uv venv
uv sync
# In Docker, rebuild
docker compose -f compose/docker-compose.dev.yml up --build
Issue 4: Dependency Conflicts¶
Symptoms:
- UV cannot resolve compatible versions
- Conflicting version requirements
- Resolution fails with error messages
Cause: Incompatible version constraints in dependencies.
Solution:
# Check conflict details
uv add package-name --verbose
# Loosen version constraints in pyproject.toml
# Change: "package==1.0.0"
# To: "package>=1.0.0,<2.0.0"
# Exclude problematic versions
uv add "package>=1.0.0,!=1.5.0"
# Update lockfile
uv lock
Best Practices¶
Command Usage¶
Always Use Modern Commands:
- Use
uv addfor adding dependencies (notuv pip install) - Use
uv removefor removing dependencies - Use
uv syncafter pulling changes - Use
uv runto execute commands with project dependencies - Use
uv lockto update lockfile without installing
Avoid Legacy Commands:
- Avoid
uv pip install(useuv addinstead) - Avoid
uv pip uninstall(useuv removeinstead) - Never mix UV with pip/poetry in same project
Version Control¶
Always Commit:
- Commit
pyproject.toml(project configuration) - Commit
uv.lock(exact dependency versions) - Commit
.python-version(Python version pinning)
Never Commit:
- Never commit
.venv/directory - Never commit
__pycache__/directories - Never commit
.uv/cache directory
Handling Merge Conflicts:
# When uv.lock has conflicts
git checkout --theirs uv.lock # Or --ours
uv lock # Regenerate lockfile
uv sync # Test resolution
Docker Integration¶
Layer Caching Best Practices:
# Copy lockfile first (rarely changes)
COPY pyproject.toml uv.lock ./
RUN uv sync --no-dev
# Copy code last (changes frequently)
COPY . .
Multi-Stage Optimization:
- Use builder stage for dependency installation
- Copy only
.venvto production stage - Use
--frozenflag for deterministic builds - Set
UV_COMPILE_BYTECODE=1for faster startup
Performance Optimization¶
UV Caching:
# Show cache location
uv cache dir
# Show cache size
uv cache size
# Clean cache (rarely needed)
uv cache clean
Parallel Installation:
- UV automatically parallelizes installations
- No configuration needed
- Significantly faster than pip
Bytecode Compilation:
Common Mistakes to Avoid¶
Don't Do These:
- Don't use
uv pip installin modern projects (useuv add) - Don't edit
uv.lockmanually (always regenerate withuv lock) - Don't commit
.venv/directory to git - Don't mix UV with pip/poetry in same project
- Don't ignore lockfile merge conflicts (resolve carefully)
- Don't use
pipinside UV-managed projects
Do These Instead:
- Use
uv addfor all dependency additions - Let UV manage
uv.lockautomatically - Add
.venv/to.gitignore - Choose one tool (UV) and stick with it
- Resolve lockfile conflicts then regenerate
- Use UV commands exclusively
Quick Command Cheat Sheet¶
Common Commands:
# Dependency Management
uv add package # Add dependency
uv add --dev package # Add dev dependency
uv remove package # Remove dependency
uv sync # Sync environment with lockfile
uv lock # Update lockfile
uv lock --upgrade # Upgrade all packages
# Running Code
uv run python script.py # Run script
uv run -m pytest # Run module
uv run uvicorn app:main # Run server
# Information
uv tree # Show dependency tree
uv pip list # List installed packages
uv --version # Show UV version
Docker Commands (Dashtam-Specific):
# Add dependency in container
docker compose -f compose/docker-compose.dev.yml exec app uv add package
# Sync environment
docker compose -f compose/docker-compose.dev.yml exec app uv sync
# Run tests
docker compose -f compose/docker-compose.dev.yml exec app uv run pytest
# Show dependencies
docker compose -f compose/docker-compose.dev.yml exec app uv tree
Next Steps¶
After mastering UV package management, consider:
- Review Docker Refactoring Implementation Guide
- Set up automated dependency updates with Dependabot
- Configure pre-commit hooks for lockfile validation
- Implement dependency security scanning
- Explore UV workspaces for monorepo projects
- Set up UV caching in CI/CD pipeline
- Document project-specific UV workflows
- Train team members on UV best practices
References¶
- UV Documentation - Official UV documentation
- UV GitHub Repository - Source code and issues
- PEP 621 - Project metadata standard
WARP.md(project root) - Project rules for UV usage- Docker Best Practices - Docker optimization
Document Information¶
Template: guide-template.md Created: 2025-10-04 Last Updated: 2025-10-20