Home > Backend Development > Python Tutorial > Scalable Python backend: Building a containerized FastAPI Application with uv, Docker, and pre-commit: a step-by-step guide

Scalable Python backend: Building a containerized FastAPI Application with uv, Docker, and pre-commit: a step-by-step guide

Susan Sarandon
Release: 2025-01-17 22:17:12
Original
613 people have browsed it

In today's containerized world, efficient backend application deployment is crucial. FastAPI, a popular Python framework, excels at creating fast, high-performance APIs. We'll use uv, a package manager, to streamline dependency management.

uv

Assuming you've installed uv and Docker, let's create our app: uv init simple-app. This generates:

<code>simple-app/
├── .python-version
├── README.md
├── hello.py
└── pyproject.toml</code>
Copy after login

pyproject.toml holds project metadata:

<code class="language-toml">[project]
name = "simple-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []</code>
Copy after login

Add project dependencies to pyproject.toml:

<code class="language-toml">dependencies = [
    "fastapi[standard]=0.114.2",
    "python-multipart=0.0.7",
    "email-validator=2.1.0",
    "pydantic>2.0",
    "SQLAlchemy>2.0",
    "alembic=1.12.1",
]

[tool.uv]
dev-dependencies = [
    "pytest=7.4.3",
    "mypy=1.8.0",
    "ruff=0.2.2",
    "pre-commit=4.0.0",
]</code>
Copy after login

The [tool.uv] section defines development dependencies excluded during deployment. Run uv sync to:

  1. Create uv.lock.
  2. Create a virtual environment (.venv). uv downloads a Python interpreter if needed.
  3. Install dependencies.

FastAPI

Create the FastAPI application structure:

<code>recipe-app/
├── app/
│   ├── main.py
│   ├── __init__.py
│   └── ...
├── .python-version
├── README.md
└── pyproject.toml</code>
Copy after login

In app/main.py:

<code class="language-python">from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Hello(BaseModel):
    message: str

@app.get("/", response_model=Hello)
async def hello() -> Hello:
    return Hello(message="Hi, I am using FastAPI")</code>
Copy after login

Run with: uv run fastapi dev app/main.py. You'll see output similar to:

Scalable Python backend: Building a containerized FastAPI Application with uv, Docker, and pre-commit: a step-by-step guide

Access it at https://www.php.cn/link/c099034308f2a231c24281de338726c1.

Docker

Let's Dockerize. We'll develop within containers. Add a Dockerfile:

<code class="language-dockerfile">FROM python:3.11-slim

ENV PYTHONUNBUFFERED=1

COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /uvx /bin/

ENV UV_COMPILE_BYTE=1
ENV UV_LINK_MODE=copy

WORKDIR /app

ENV PATH="/app/.venv/bin:$PATH"

COPY ./pyproject.toml ./uv.lock ./.python-version /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-project --no-dev

COPY ./app /app/app

RUN --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen --no-dev

CMD ["fastapi", "dev", "app/main.py", "--host", "0.0.0.0"]</code>
Copy after login

For easier container management, use docker-compose.yaml:

<code class="language-yaml">services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    working_dir: /app
    volumes:
      - ./app:/app/app
    ports:
      - "${APP_PORT:-8000}:8000"
    environment:
      - DATABASE_URL=${DATABASE_URL}
    depends_on:
      - postgres

  postgres:
    image: postgres:15
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data: {}</code>
Copy after login

Create a .env file with environment variables. Run with: docker compose up --build.

[tool.uv] and Development Tools

The [tool.uv] section in pyproject.toml lists development tools:

  • pytest: Testing framework (out of scope here).
  • mypy: Static type checker. Run manually: uv run mypy app.
  • ruff: Fast linter (replaces multiple tools).
  • pre-commit: Manages pre-commit hooks. Create .pre-commit-config.yaml:
<code class="language-yaml">repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: check-added-large-files
      - id: check-toml
      - id: check-yaml
        args:
          - --unsafe
      - id: end-of-file-fixer
      - id: trailing-whitespace
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.8.6
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format</code>
Copy after login

Add pyproject.toml configurations for mypy and ruff (example provided in the original text). Install a VS Code Ruff extension for real-time linting. This setup ensures consistent code style, type checking, and pre-commit checks for a streamlined workflow.

The above is the detailed content of Scalable Python backend: Building a containerized FastAPI Application with uv, Docker, and pre-commit: a step-by-step guide. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template