DEV Community

Cover image for Efficient Python Dependency Management with uv in Docker for FastAPI
Mohamed Abdelwahed
Mohamed Abdelwahed

Posted on

Efficient Python Dependency Management with uv in Docker for FastAPI

In modern Python development, managing project dependencies efficiently is crucial for optimizing both development and production environments. In this post, we'll focus on using the uv package manager to streamline Python dependency management in a Dockerized FastAPI application.

The Role of uv in Dependency Management

uv is a high-performance package manager designed to make Python dependency management faster, more reproducible, and less resource-intensive. Unlike traditional tools like pip and virtualenv, uv focuses on reducing complexity and enhancing speed by syncing your dependencies based on a lock file. By using uv, you can ensure that only the necessary system dependencies are installed, avoiding unnecessary overhead and improving the overall performance of your containerized application.

Dockerfile for FastAPI Application with uv

FROM python:3.12-alpine

# Install system dependencies required by uv
RUN apk add --no-cache curl git

# Install uv safely
RUN curl -LsSf -o /tmp/install_uv.sh https://astral.sh/uv/install.sh && \
    sh /tmp/install_uv.sh && \
    rm /tmp/install_uv.sh

# Set PATH to include uv
ENV PATH="/root/.local/bin:$PATH"

# Create app directory and set permissions
WORKDIR /app

# Copy dependency files first for caching
COPY pyproject.toml uv.lock ./

# Install dependencies using uv
RUN uv sync --frozen --no-install-project --no-dev --python-preference=only-system

# Copy the rest of the project files
COPY . .

# Run the FastAPI application
CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
Enter fullscreen mode Exit fullscreen mode

Breakdown of the Dockerfile and uv Integration

1. Base Image and System Dependencies

FROM python:3.12-alpine
RUN apk add --no-cache curl git
Enter fullscreen mode Exit fullscreen mode

We start by using the official python:3.12-alpine image, which is optimized for small size. Then, we install system dependencies curl and git, which are required for installing uv and potentially fetching git-based dependencies.

2. Installing uv

RUN curl -LsSf -o /tmp/install_uv.sh https://astral.sh/uv/install.sh && \
    sh /tmp/install_uv.sh && \
    rm /tmp/install_uv.sh
Enter fullscreen mode Exit fullscreen mode

The core of this Dockerfile is the installation of the uv package manager. uv is installed by downloading and running the installer script. This step ensures that your project uses a fast, consistent, and lean dependency management tool. The installer script installs uv to the /root/.local/bin directory.

3. Setting Up uv in the Environment

ENV PATH="/root/.local/bin:$PATH"
Enter fullscreen mode Exit fullscreen mode

Here, we add the directory where uv is installed to the PATH environment variable, ensuring it is accessible in subsequent Docker commands.

4. Copying Dependency Files and Installing Dependencies

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-install-project --no-dev --python-preference=only-system
Enter fullscreen mode Exit fullscreen mode
  • We copy the pyproject.toml and uv.lock files, which contain all the necessary dependency information for the project.
  • We then use uv sync to install dependencies. The --frozen flag ensures that the exact versions from uv.lock are used, and --no-install-project avoids installing the project itself, focusing solely on dependencies. The --no-dev option skips installing development dependencies, while --python-preference=only-system ensures system dependencies are prioritized, minimizing the size of the image.

5. Copying Application Code

COPY . .
Enter fullscreen mode Exit fullscreen mode

This command copies the remaining application files into the container. Since dependencies were already installed earlier, Docker will skip unnecessary installations if the code changes.

6. Running the FastAPI Application

CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
Enter fullscreen mode Exit fullscreen mode

Finally, we use uv to launch the FastAPI application with uvicorn as the ASGI server. The app is configured to listen on port 80, and 0.0.0.0 ensures it's accessible externally.

Why Choose uv?

  • Speed: uv is optimized for performance and installs dependencies faster than traditional tools, especially in containerized environments where build times matter.
  • Reproducibility: By relying on uv.lock and using the --frozen flag, you ensure that every environment running the Docker container uses the same dependency versions, making builds more predictable and stable.
  • Lean Builds: uv avoids unnecessary installations of development dependencies or redundant Python packages, reducing the overall size of your Docker image.

Conclusion

Using uv in your Dockerfile offers significant improvements in dependency management, speed, and image size. The approach outlined here ensures that your FastAPI application is built on a reproducible, efficient foundation, making it easy to deploy and scale. By integrating uv, you not only streamline the installation process but also improve the overall stability and performance of your application in production environments.

Top comments (0)