资讯动态

FastAPI应用Docker容器化部署实战:从镜像构建到Compose编排

发布时间:2026/8/24 2:25:34 来源:尧图企业网站定制
这次我们来看一个 FastAPI 课程更新 Docker 部署内容的项目。对于正在学习或使用 FastAPI 开发 Web API 的开发者来说如何将应用打包、分发并稳定运行在服务器上是项目从开发走向部署的关键一步。Docker 部署正是解决环境一致性、简化部署流程的核心技术。这次课程更新重点就是打通从 FastAPI 代码到 Docker 容器化服务的完整链路。课程的核心价值在于提供一套可落地的操作方案而不是空谈概念。它关注的是你的 FastAPI 应用如何写 Dockerfile、如何构建镜像、如何配置环境变量、如何管理依赖、以及最终如何通过一条命令启动服务。对于个人项目测试、团队协作交付或是需要快速在云服务器上拉起一个 API 服务这套方法都能直接套用。本文将带你快速梳理这次课程更新的核心内容。我们会重点关注如何将一个基础的 FastAPI 应用 Docker 化包括镜像构建优化、多阶段构建以减小体积、环境变量配置、端口映射以及使用 Docker Compose 编排更复杂的服务例如包含数据库。同时也会涉及在部署中常见的坑点比如时区设置、文件挂载权限、依赖缓存优化等。无论你是刚接触 Docker还是想优化现有的部署流程这篇文章都能提供清晰的步骤和可复用的代码示例。1. 核心能力速览能力项说明项目类型FastAPI 应用 Docker 容器化部署教程/课程更新技术栈FastAPI, Python, Docker, Docker Compose主要功能将 FastAPI 应用打包为 Docker 镜像实现一键部署与运行环境门槛支持 Windows/macOS/Linux需安装 Docker 及 Docker Compose资源占用取决于应用本身及基础镜像通常镜像体积可优化至百兆级别启动方式命令行docker run或docker-compose up是否支持 API是部署后即提供完整的 FastAPI API 服务是否支持批量/CI是镜像可用于 CI/CD 流水线实现自动化构建与部署适合场景开发环境统一、测试环境快速搭建、生产环境服务部署、微服务架构2. 适用场景与使用边界这个课程内容主要面向以下几类开发者FastAPI 初学者已经写完第一个 API但不知道如何让别人也能运行起来。全栈开发者需要将后端 API 部署到云服务器供前端应用调用。运维或 DevOps 工程师需要为团队制定标准的应用打包和部署规范。项目管理者希望实现开发、测试、生产环境的一致性减少“在我机器上能跑”的问题。它能解决的核心问题环境隔离避免因本地 Python 版本、包版本差异导致的服务运行异常。简化部署服务器上只需安装 Docker无需再折腾 Python 环境、虚拟环境、依赖安装。便于迁移与扩展镜像可以在任何支持 Docker 的平台上运行轻松实现水平扩展。提升协作效率新成员拉取代码和镜像后能快速启动完整的服务环境。不适合的场景与边界超轻量级脚本如果只是一个简单的、无依赖的脚本直接运行可能更简单。对容器技术有严格限制的环境某些特定监管或安全要求的环境可能禁止使用容器。性能极致敏感型应用容器化会带来极轻微的性能开销通常可忽略但对于需要榨干硬件性能的场景需评估。版权与合规确保你打包到镜像中的代码、依赖库均拥有合法的使用授权。严禁将含有未授权商业软件或敏感数据的镜像公开传播。3. 环境准备与前置条件在开始 Docker 化你的 FastAPI 应用之前需要确保本地环境就绪。1. 操作系统Windows 10/11专业版/企业版/教育版支持 WSL2、macOS 或 Linux 发行版如 Ubuntu, CentOS。2. Docker 环境这是最核心的依赖。你需要安装 Docker Engine 和 Docker Compose。Docker Desktop (Windows/macOS)推荐初学者使用它集成了 Docker Engine、Docker CLI 和 Docker Compose并提供图形界面。访问 Docker 官网下载安装包。Linux 安装通过包管理器安装例如 Ubuntu# 更新软件包索引并安装必要工具 sudo apt-get update sudo apt-get install ca-certificates curl gnupg # 添加 Docker 官方 GPG 密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg # 设置存储库 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装 Docker sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin # 验证安装 sudo docker run hello-world3. 基础 FastAPI 应用确保你有一个可以正常运行的 FastAPI 应用。一个最简单的main.py示例如下from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class Item(BaseModel): name: str price: float app.get(/) def read_root(): return {Hello: World} app.post(/items/) def create_item(item: Item): return {item_name: item.name, item_price: item.price}4. 依赖管理文件requirements.txt在项目根目录下需要有列出所有 Python 依赖的文件。fastapi0.104.1 uvicorn[standard]0.24.0 # 其他依赖如 sqlalchemy, pymysql, redis 等5. 端口检查确保你计划映射的宿主机端口如8000没有被其他程序占用。4. 安装部署与启动方式Docker 部署的核心是编写Dockerfile和docker-compose.yml文件。我们将从简单到复杂分步实现。4.1 基础 Dockerfile 构建与运行在 FastAPI 项目根目录下创建Dockerfile文件无后缀名。1. 编写基础 Dockerfile# 使用官方 Python 运行时作为父镜像 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 将当前目录内容复制到容器的 /app 下 COPY . /app # 安装项目依赖 RUN pip install --no-cache-dir -r requirements.txt # 暴露端口FastAPI 默认在 8000 端口运行 EXPOSE 8000 # 容器启动时运行的命令 CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000]2. 构建 Docker 镜像在包含Dockerfile的目录下打开终端执行构建命令。-t参数用于给镜像命名和打标签。docker build -t my-fastapi-app:latest .这个过程会下载 Python 基础镜像并执行Dockerfile中的指令。首次构建可能较慢。3. 运行 Docker 容器镜像构建成功后使用docker run命令启动容器。docker run -d --name fastapi-container -p 8000:8000 my-fastapi-app:latest-d: 后台运行容器。--name: 给容器指定一个名称便于管理。-p 8000:8000: 端口映射将宿主机的 8000 端口映射到容器的 8000 端口。4. 验证服务打开浏览器访问http://localhost:8000/docs你应该能看到 FastAPI 自动生成的交互式 API 文档 Swagger UI。访问http://localhost:8000应返回{Hello: World}。4.2 优化使用多阶段构建减小镜像体积基础镜像python:3.11-slim已经比较小但我们可以通过多阶段构建进一步优化分离构建环境和运行环境移除构建工具等不必要的文件。# 第一阶段构建阶段 FROM python:3.11 as builder WORKDIR /app # 复制依赖文件 COPY requirements.txt . # 安装依赖到 /usr/local/lib/python3.11/site-packages RUN pip install --user --no-cache-dir -r requirements.txt # 第二阶段运行阶段 FROM python:3.11-slim WORKDIR /app # 从构建阶段复制已安装的依赖 COPY --frombuilder /root/.local /root/.local # 复制应用代码 COPY . . # 确保 pip 安装的包在 PATH 中 ENV PATH/root/.local/bin:$PATH EXPOSE 8000 CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000]重新构建并运行镜像体积会有显著减小。4.3 进阶使用 Docker Compose 编排服务当你的应用需要连接数据库如 PostgreSQL、MySQL、缓存如 Redis或其他服务时使用 Docker Compose 可以一键启动所有相关容器并管理它们之间的网络。1. 编写docker-compose.yml在项目根目录创建docker-compose.yml文件。version: 3.8 services: web: build: . container_name: fastapi_app ports: - 8000:8000 # 环境变量配置可以从 .env 文件读取 environment: - DATABASE_URLpostgresql://user:passworddb:5432/mydb # 依赖服务确保 db 先启动 depends_on: - db # 挂载代码目录便于开发时热重载生产环境不建议 volumes: - ./:/app # 覆盖 Dockerfile 中的 CMD开发时使用 --reload command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload db: image: postgres:15-alpine container_name: postgres_db environment: - POSTGRES_USERuser - POSTGRES_PASSWORDpassword - POSTGRES_DBmydb volumes: - postgres_data:/var/lib/postgresql/data ports: - 5432:5432 # 仅开发时暴露生产环境可移除 volumes: postgres_data:2. 使用 Docker Compose 启动服务在docker-compose.yml所在目录执行# 启动所有服务后台运行 docker-compose up -d # 查看运行状态 docker-compose ps # 查看日志 docker-compose logs -f web # 停止并移除所有容器、网络保留数据卷 docker-compose down # 停止并移除所有容器、网络、数据卷 docker-compose down -v5. 功能测试与效果验证部署完成后我们需要验证服务是否按预期工作并测试其稳定性和性能边界。5.1 基础 API 连通性测试测试目的确认 FastAPI 服务已成功启动核心接口可访问。访问文档浏览器打开http://localhost:8000/docs或http://localhost:8000/redoc应能正常加载 Swagger UI 或 ReDoc 文档页面。测试 GET 接口使用curl或 Postman 测试根路径。curl http://localhost:8000/预期返回{Hello:World}。测试 POST 接口测试带请求体的接口。curl -X POST http://localhost:8000/items/ \ -H Content-Type: application/json \ -d {name:Foo, price: 50.5}预期返回{item_name:Foo,item_price:50.5}。判断成功以上请求均返回正确的 HTTP 状态码如 200和预期数据。5.2 数据库连接测试如果使用了 Compose测试目的验证 FastAPI 应用容器是否能成功连接并操作数据库容器。修改 FastAPI 应用在main.py中增加一个简单的数据库连接测试端点示例使用异步 SQLAlchemy asyncpg。from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker import os DATABASE_URL os.getenv(DATABASE_URL, postgresqlasyncpg://user:passworddb:5432/mydb) engine create_async_engine(DATABASE_URL, echoTrue) AsyncSessionLocal sessionmaker(engine, class_AsyncSession, expire_on_commitFalse) app.get(/test_db) async def test_db_connection(): async with AsyncSessionLocal() as session: # 执行一个简单的查询 result await session.execute(SELECT 1) return {database: connected, result: result.scalar()}同时更新requirements.txt添加sqlalchemy[asyncio]和asyncpg。重建并启动服务docker-compose down docker-compose up -d --build测试接口curl http://localhost:8000/test_db预期返回{database:connected,result:1}。判断成功接口返回连接成功信息且 Docker Compose 日志 (docker-compose logs db) 中能看到来自fastapi_app容器的连接日志。5.3 容器健康与资源观察测试目的监控容器运行状态和资源消耗。查看容器列表docker ps确认fastapi_app和postgres_db容器状态为Up。查看容器资源占用docker stats fastapi_app观察 CPU、内存、网络 I/O 使用情况。一个简单的 FastAPI 应用通常占用内存很少。进入容器内部调试docker exec -it fastapi_app /bin/bash可以在容器内检查文件、运行命令例如pip list查看已安装包。6. 接口 API 与批量任务Docker 化后的 FastAPI 应用其 API 调用方式与本地运行完全一致只是主机地址变成了容器所在的宿主机地址或容器网络内的服务名。6.1 外部调用 API假设服务运行在宿主机 IP192.168.1.100的 8000 端口。import requests import json base_url http://192.168.1.100:8000 # 测试 GET response requests.get(f{base_url}/) print(fGET / Status: {response.status_code}, Response: {response.json()}) # 测试 POST item_data {name: DockerBook, price: 99.9} response requests.post(f{base_url}/items/, jsonitem_data) print(fPOST /items/ Status: {response.status_code}, Response: {response.json()})6.2 处理批量任务异步任务示例对于需要长时间运行的批量任务如处理大量数据、发送邮件应在 FastAPI 内使用后台任务或消息队列避免阻塞 HTTP 请求。示例使用BackgroundTasksfrom fastapi import BackgroundTasks import time def write_log(message: str): time.sleep(2) # 模拟耗时操作 with open(log.txt, modea) as log: log.write(f{message}\n) app.post(/batch/) async def start_batch_task(info: str, background_tasks: BackgroundTasks): background_tasks.add_task(write_log, fProcessing: {info}) return {message: Batch task started in background.}调用此接口会立即返回而写日志的任务会在后台异步执行。在 Docker 容器中日志文件会写入容器的文件系统。重要提醒对于更复杂的批量任务或需要持久化的任务应考虑使用 Celery Redis/RabbitMQ 等专业任务队列并将这些服务也通过 Docker Compose 进行编排。7. 资源占用与性能观察Docker 容器本身开销很低性能影响主要来自应用本身和镜像层次。镜像体积优化使用 Alpine 或 Slim 镜像python:3.11-alpine比python:3.11-slim更小但可能缺少某些编译工具安装某些依赖时可能需要额外系统包。多阶段构建如前所述是减小镜像体积的最有效手段。清理缓存在RUN命令中合并apt-get update apt-get install -y ... rm -rf /var/lib/apt/lists/*和pip install --no-cache-dir来减少层大小。使用docker image ls查看镜像大小。容器运行时资源内存与 CPU 限制在生产环境中可以使用docker run的-m、--cpus参数或docker-compose.yml中的deploy.resources.limits来限制容器资源防止单个容器耗尽主机资源。# docker-compose.yml 示例 services: web: # ... deploy: resources: limits: cpus: 0.5 memory: 512M监控使用docker stats或集成 Prometheus、cAdvisor 等工具进行监控。文件系统性能卷挂载 (Volumes)对于需要持久化或频繁读写的数据库数据、上传的文件等务必使用 Docker 卷 (volumes) 或绑定挂载而不是写入容器内部的可写层以获得更好的 I/O 性能和数据持久性。开发时的卷挂载开发时挂载代码目录 (./:/app) 方便热重载但会带来宿主机与容器间的文件同步开销。生产环境应直接将代码复制进镜像。8. 常见问题与排查方法问题现象可能原因排查方式解决方案docker build失败提示pip install错误1. 网络问题无法访问 PyPI。2.requirements.txt中包版本冲突或不存。3. 缺少系统级依赖如 gcc。1. 检查网络尝试pip install单个包。2. 查看错误日志确认具体是哪个包失败。3. 对于需要编译的包确保基础镜像包含build-essential等工具。1. 配置国内镜像源。2. 调整requirements.txt使用兼容的版本。3. 在 Dockerfile 的RUN pip install前先安装系统依赖RUN apt-get update apt-get install -y gcc ...。docker run后访问localhost:8000连接被拒绝1. 容器启动失败。2. 端口映射错误。3. 应用在容器内未监听0.0.0.0。1.docker ps查看容器是否在运行。2.docker logs container_name查看应用启动日志。3.docker port container_name查看端口映射。1. 根据日志修复应用错误。2. 检查-p参数或docker-compose.yml的ports配置。3. 确保 FastAPI 启动命令包含--host 0.0.0.0。应用无法连接数据库在 Compose 中1. 数据库服务未启动。2. 连接字符串主机名、端口、密码错误。3. 网络不在同一 Docker 网络。1.docker-compose ps确认所有服务状态。2.docker-compose logs db查看数据库日志。3. 在应用容器内使用ping db测试网络连通性。1. 确保depends_on配置正确。2. 检查环境变量DATABASE_URL或相关配置在 Compose 中服务名如db可作为主机名。3. Docker Compose 默认会创建并共用同一个网络。容器内应用时区不对容器默认使用 UTC 时区。在容器内执行date命令。在 Dockerfile 中设置时区ENV TZAsia/ShanghaiRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ /etc/timezone镜像体积过大1. 使用了过大的基础镜像如python:3.11。2. 每一层都累积了缓存或中间文件。docker image ls查看镜像大小。docker history image_name查看各层大小。1. 使用多阶段构建。2. 使用slim或alpine版本基础镜像。3. 在同一RUN指令中清理缓存。docker-compose up提示端口已被占用宿主机端口已被其他进程使用。netstat -tuln | grep :8000(Linux) 或Get-NetTCPConnection -LocalPort 8000(PowerShell)1. 停止占用端口的进程。2. 修改docker-compose.yml中的端口映射如- 8080:8000。容器内应用写入的文件在宿主机找不到文件写入了容器的可写层容器删除后文件丢失。检查 Dockerfile 或运行命令中是否定义了卷挂载。对于需要持久化的数据如日志、上传的文件使用 Docker 卷或绑定挂载到宿主机目录。9. 最佳实践与使用建议开发与生产配置分离使用不同的Dockerfile如Dockerfile.dev,Dockerfile.prod或通过构建参数 (--build-arg) 来区分环境。在docker-compose.yml中使用env_file指定不同的环境变量文件如.env.dev,.env.prod避免将敏感信息数据库密码、API密钥硬编码在文件中。利用.dockerignore文件 在项目根目录创建.dockerignore忽略不需要拷贝进镜像的文件如虚拟环境目录、日志、IDE配置、git历史等可以加速构建过程并减小镜像体积。__pycache__ *.pyc .venv env .git .idea *.log .env镜像标签与版本管理为镜像打上有意义的标签如myapp:1.0.0,myapp:latest。在 CI/CD 流水线中可以使用 Git 提交哈希作为标签的一部分确保可追溯性。健康检查 在 Dockerfile 或 docker-compose.yml 中配置健康检查让 Docker 能够判断容器内应用是否真的“就绪”。# Dockerfile 示例 HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost:8000/health || exit 1# docker-compose.yml 示例 services: web: # ... healthcheck: test: [CMD, curl, -f, http://localhost:8000/health] interval: 30s timeout: 3s retries: 3 start_period: 5s日志管理确保应用将日志输出到标准输出 (stdout) 和标准错误 (stderr)这样可以通过docker logs查看。对于生产环境考虑使用json-file或journald日志驱动或者将日志收集到 ELK、Loki 等集中式日志系统。安全建议不要以 root 用户运行应用。在 Dockerfile 中创建非特权用户并切换。RUN addgroup --system appgroup adduser --system --group appuser USER appuser定期更新基础镜像和应用依赖修复安全漏洞。将 FastAPI 应用 Docker 化是迈向现代化应用部署和运维的关键一步。这套方法的核心优势在于标准化和可重复性。通过本课程更新所涵盖的内容你不仅能把应用跑起来更能理解如何优化镜像、编排多服务、配置环境以及排查问题。最值得尝试的起点是为你现有的一个简单 FastAPI 项目编写Dockerfile并成功运行。在这个过程中你可能会遇到依赖安装、端口冲突等问题对照第 8 节的排查表基本都能解决。之后再尝试引入 Docker Compose 来管理数据库体验一键启动完整开发环境的便利。最容易踩的坑往往在初期忘记暴露端口、应用未监听0.0.0.0、数据库连接字符串配置错误。按照本文的步骤和验证方法可以系统地避免这些问题。下一步你可以探索更深入的领域例如将构建好的镜像推送到 Docker Hub 或私有仓库在 Kubernetes 中部署你的 FastAPI 服务或者为你的 CI/CD 流水线如 GitHub Actions, GitLab CI添加自动构建和部署 Docker 镜像的步骤。容器化是起点它为你打开了通往云原生和自动化运维的大门。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价