0

0

可扩展的 Python 后端:使用 uv、Docker 和预提交构建容器化 FastAPI 应用程序:分步指南

心靈之曲

心靈之曲

发布时间:2025-01-17 23:20:01

|

807人浏览过

|

来源于dev.to

转载

在当今容器化部署的世界中,高效构建和部署后端应用程序至关重要。 fastapi 已成为创建快速、高性能 api 的最流行的 python 框架之一。为了管理依赖关系,我们还可以利用 uv(包管理器)作为一个方便的工具。

紫外线

我假设您之前已经在本地安装了 uv 和 docker

现在,我们可以通过使用以下命令初始化我们的项目来继续创建我们的应用程序: uv init simple-app

uv 将创建以下文件:

simple-app/
├── .python-version
├── readme.md
├── hello.py
└── pyproject.toml

pyproject.toml 文件包含有关我们项目的元数据:

[project]
name = "simple-app"
version = "0.1.0"
description = "add your description here"
readme = "readme.md"
requires-python = ">=3.11"
dependencies = []

接下来,我们可以开始添加项目依赖项。您最终应该在 pyproject.toml 中得到以下结构:

dependencies = [
    "fastapi[standard]<1.0.0,>=0.114.2",
    "python-multipart<1.0.0,>=0.0.7",
    "email-validator<3.0.0,>=2.1.0",
    "pydantic>2.0",
    "sqlalchemy>2.0",
    "alembic<2.0.0,>=1.12.1",
    ]

[tool.uv]
dev-dependencies = [
    "pytest<8.0.0,>=7.4.3",
    "mypy<2.0.0,>=1.8.0",
    "ruff<1.0.0,>=0.2.2",
    "pre-commit<4.1.0,>=4.0.0",
]

注意 [tool.uv] 部分:在这里,我们定义了一些在部署项目时将排除的依赖项,因为在该阶段不需要它们。

此时,我们还没有创建任何虚拟环境。为此,只需运行:uvsync,uv 将执行以下操作

立即学习Python免费学习笔记(深入)”;

  1. 创建 uv.lock 文件。
  2. 使用指定的python版本(如pyproject.toml中的.python-version和requires-python所示)创建虚拟环境(.venv文件夹)。如果 uv 找不到本地 python 解释器,它将下载一个。
  3. 安装所有依赖项。

快速api

现在,我们可以通过添加以下文件夹结构来开始手动创建 fastapi 应用程序:

recipe-app/
├── app/
│   ├── main.py
│   ├── __init__.py
│   └── ...
├── .python-version
├── readme.md
└── pyproject.toml

在main.py中,添加以下代码:

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")

我们可以通过执行以下命令来运行我们的项目:uv run fastapi dev app/main.py,您应该看到类似于以下内容的输出

fastapi running locally.

如果您转到http://127.0.0.1:8000/,,您将看到:消息“嗨,我正在使用 fastapi”

码头工人

到目前为止,一切都很好。但是,我们还没有集成 docker。我们将使用容器进行开发(有人认为这不方便,但这最终取决于您)。另外,我们将在容器内使用 uv,这可能是有争议的,但这是我习惯的。

uv 在这里提供了一些有关在 docker 中使用 uv 的有用信息。我们首先使用以下配置在应用程序的根目录添加 dockerfile:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载
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

# change the working directory to the `app` directory
workdir /app

env path="/app/.venv/bin:$path"

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

# copy the project into the image
copy ./app /app/app

# sync the project
run --mount=type=cache,target=/root/.cache/uv \
    uv sync --frozen --no-dev

cmd ["fastapi", "dev", "app/main.py", "--host", "0.0.0.0"]
虽然您可以创建多阶段 dockerfile,但我们在本教程中让事情变得更简单。

我们可以只使用我们的容器,但是我发现创建一个 docker-compose.yaml 文件来管理我们所有的容器更方便:

services:
  app:
    # build configuration for the "app" service:
    # - 'context: .' tells docker to use the current directory as the build context
    # - 'dockerfile: dockerfile' specifies the file to use for building the image
    build:
      context: .
      dockerfile: dockerfile

    # this sets the default working directory inside the container
    working_dir: /app

    # mounts the local "app" directory into the container so code changes are reflected without rebuild
    volumes:
      - ./app:/app/app

    # maps the container port 8000 to the host machine port defined by app_port
    # if app_port is not set, it defaults to 8000
    ports:
      - "${app_port:-8000}:8000"

    # passes the database_url environment variable to the container
    environment:
      - database_url=${database_url}

    # ensures the 'app' service won't start until 'postgres' is running
    depends_on:
      - postgres

  postgres: ## just for reference...
    # official postgres image version 15
    image: postgres:15

    # set up the default database, user, and password
    environment:
      postgres_db: ${postgres_db}
      postgres_user: ${postgres_user}
      postgres_password: ${postgres_password}

    # this volume stores postgresql data outside of the container filesystem,
    # preserving data between container restarts or recreations
    volumes:
      - postgres_data:/var/lib/postgresql/data

# declare named volumes to be used for persistent storage
volumes:
  postgres_data: {}

要运行所有容器,请创建一个包含所有必需变量的 .env 文件。

您可能想知道为什么我们需要两次定义数据库凭据。嗯,database_url 用于 alembic 和 sqlalchemy,各个凭据用于数据库本身。这看似重复,但我们只需要配置一次。

一切设置完毕后,我们可以使用以下命令运行我们的项目: docker compose up --build

[工具.uv]

我们需要介绍的最后一部分是 pyproject.toml 中的 [tool.uv] 部分,我们在其中列出了开发依赖项。

  • pytest

    • pytest 是 python 中广泛使用的测试框架,允许您编写小型、简洁的测试,同时提供强大的功能,例如固定装置和断言。
  • mypy

    • mypy 是 python 的静态类型检查器,它使用类型提示 (pep 484) 在运行前检测潜在的错误或不一致。
  • 皱褶

    • ruff 是一个快速的 python linter,用 rust 编写,能够通过提供彻底的样式、错误和格式检查来替换多个工具(例如 flake8、isort)。
  • 预提交

    • 预提交是一个用于管理和维护多语言预提交挂钩的框架,通过在提交最终确定之前运行检查来确保代码库的一致性和质量。

由于 pytest 超出了范围,我们将首先配置 ruff 并预提交。我们需要创建一个 .pre-commit-config.yaml 文件,每次执行 git 提交操作时都会运行该文件。以下是建议的配置:

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

您也可以在预提交中配置 mypy,但这可能有点棘手,因为它需要一个隔离的环境来检查您的代码,并且可能无法找到已经属于您的依赖项的包。这就是为什么我更喜欢通过执行以下命令来手动运行它: uv run mypy app 它将在我们的应用程序文件夹上运行 mypy。

可以为 mypy 和 ruff 添加额外的配置到 pyproject.toml 中。这是我的标准配置(有些值是默认值,但我更喜欢明确):

[tool.mypy]
strict = true
exclude = ["venv", ".venv", "alembic"]
ignore_missing_imports = true
allow_untyped_decorators = true
plugins = ["pydantic.mypy"]
follow_imports = "silent"
warn_redundant_casts = true
warn_unused_ignores = true
disallow_any_generics = true
no_implicit_reexport = true
disallow_untyped_defs = true

[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
warn_required_dynamic_aliases = true

[tool.ruff]
target-version = "py312"
exclude = ["venv", ".venv", "alembic"]
line-length = 100
indent-width = 4

[tool.ruff.lint]
select = [
    "E",  # pycodestyle errors
    "W",  # pycodestyle warnings
    "F",  # pyflakes
    "I",  # isort
    "B",  # flake8-bugbear
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade
    "ARG001", # unused arguments in functions
]
ignore = [
    "B008",  # do not perform function calls in argument defaults
    "W191",  # indentation contains tabs
    "B904",  # Allow raising exceptions without from e, for HTTPException
]

[tool.ruff.format]
quote-style = "double"
line-ending = "auto"

[tool.ruff.lint.pyupgrade]
# Preserve types, even if a file imports `from __future__ import annotations`.
keep-runtime-typing = true

[tool.pyright]
ignore = ["alembic"]

现在您可以直接从 vs code marketplace 安装 ruff 扩展。该插件将自动检查您的代码并实时突出显示问题,在您工作时提供即时反馈,该扩展将考虑 pyproject.toml

中的所有配置

通过此配置,您的开发环境将强制执行一致的代码风格、类型检查和预提交检查,从而为使用 uv 构建容器化 fastapi 应用程序提供更顺畅的工作流程。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++系统编程内存管理_C++系统编程怎么与Rust竞争内存安全
C++系统编程内存管理_C++系统编程怎么与Rust竞争内存安全

C++系统编程中的内存管理是指 对程序运行时内存的申请、使用和释放进行精细控制的机制,涵盖了栈、堆、静态区等不同区域,开发者需要通过new/delete、智能指针或内存池等方式管理动态内存,以避免内存泄漏、野指针等问题,确保程序高效稳定运行。它核心在于开发者对低层内存有完全控制权,带来灵活性,但也伴随高责任,是C++性能优化的关键。

10

2025.12.22

Python FastAPI异步API开发_Python怎么用FastAPI构建异步API
Python FastAPI异步API开发_Python怎么用FastAPI构建异步API

Python FastAPI 异步开发利用 async/await 关键字,通过定义异步视图函数、使用异步数据库库 (如 databases)、异步 HTTP 客户端 (如 httpx),并结合后台任务队列(如 Celery)和异步依赖项,实现高效的 I/O 密集型 API,显著提升吞吐量和响应速度,尤其适用于处理数据库查询、网络请求等耗时操作,无需阻塞主线程。

27

2025.12.22

自建git服务器
自建git服务器

git服务器是目前流行的分布式版本控制系统之一,可以让多人协同开发同一个项目。本专题为大家提供自建git服务器相关的各种文章、以及下载和课程。

744

2023.07.05

git和svn的区别
git和svn的区别

git和svn的区别:1、定义不同;2、模型类型不同;3、存储单元不同;4、是否拥有全局版本号;5、内容完整性不同;6、版本库不同;7、克隆目录速度不同;8、分支不同。php中文网为大家带来了git和svn的相关知识、以及相关文章等内容。

559

2023.07.06

git撤销提交的commit
git撤销提交的commit

Git是一个强大的版本控制系统,它提供了很多功能帮助开发人员有效地管理和控制代码的变更,本专题为大家提供git 撤销提交的commit相关的各种文章内容,供大家免费下载体验。

268

2023.07.24

git提交错误怎么撤回
git提交错误怎么撤回

git提交错误撤回的方法:git reset head^:撤回最后一次提交,恢复到提交前状态。git revert head:创建新提交,内容与之前提交相反。git reset :使用提交的 sha-1 哈希撤回指定提交。交互式舞台区:标记要撤回的特定更改,然后提交,排除已撤回更改。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

558

2024.04.09

git怎么对比两个版本的文件内容
git怎么对比两个版本的文件内容

要对比两个版本的 git 文件,请使用 git diff 命令:git diff 比较工作树和暂存区之间的差异。git diff 比较两个提交或标签之间的差异。git diff 输出显示差异块,其中 + 表示添加的行,- 表示删除的行, 表示修改的行。可使用 gitkraken、meld、beyond compare 等可视化工具更直观地查看差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

523

2024.04.09

k8s和docker区别
k8s和docker区别

k8s和docker区别有抽象层次不同、管理范围不同、功能不同、应用程序生命周期管理不同、缩放能力不同、高可用性等等区别。本专题为大家提供k8s和docker区别相关的各种文章、以及下载和课程。

257

2023.07.24

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号