写 Python 后端的人这几年多半都绕不开 FastAPI,异步支持好,类型提示友好,自动生成的 Swagger 文档更是省了不少沟通成本。但代码写得漂亮只是故事的一半,另一半是怎么让这些代码稳稳当当地跑到生产环境里去,还不出岔子。这正是 CI/CD(持续集成/持续部署)要解决的问题。有意思的是,FastAPI 本身并不像 Django 那样自带一套官方部署框架,它更像是把选择权交还给开发者,生态里长出了不少各具特色的工具组合。下面就聊聊这套生态具体长什么样,落地时又该怎么操作。
🧭 生态概览,谁在为 FastAPI 的自动化交付出力
FastAPI 的 CI/CD 生态大致可以拆成几块拼图,测试框架、代码质量工具、容器化方案、以及编排部署的流水线服务,它们各管一段,组合起来才是完整的交付链路。
从社区实践来看,GitHub Actions 几乎是绝对主流的选择,原因也简单,代码托在 GitHub 上,Actions 天然集成,配置文件往 .github/workflows/ 目录一放就能跑起来 。当然 GitLab CI 也有一批忠实用户,尤其是企业内部自建 GitLab 实例的团队,两者的流水线思路其实高度相似 。
测试这一环几乎清一色用 pytest 搭配 FastAPI 自带的 TestClient,官方文档专门给出了示例,用 TestClient 把整个应用包起来,写测试函数跟写普通 Python 函数没什么区别 。有开发者吐槽说测试数据库这一块处理起来比想象中麻烦,得手动搭建假数据库并在测试结束后清理,不像某些 Node 生态那样有开箱即用的方案 ,但社区也总结出不少用 pytest fixture 加依赖覆写(dependency overrides)来简化这个过程的技巧 。
容器化方面,Docker 是绕不开的默认答案。FastAPI 官方文档专门写了一整章讲怎么给应用打镜像,从最基础的单文件应用到多进程多容器的复杂场景都有覆盖 。部署到生产环境时,Gunicorn 配合 Uvicorn worker 的组合被反复提及,因为 Uvicorn 单独跑起来虽然快,但缺乏 Gunicorn 那种进程管理和优雅重启的能力 。
下面这张图大致画出了一条典型的 FastAPI CI/CD 流水线是怎么流转的。
🛠 落地实操,一步步搭出可用的流水线
光看工具清单容易让人云里雾里,不如拆开来看具体怎么写配置文件,怎么串起每一步。
第一步,把测试写在最前面
流水线的第一道关卡永远是测试,这个顺序不能乱。有篇教程用了个挺形象的比喻,测试就像机场安检,代码(乘客)没过检查就别想登机(上生产环境)。一个最简单的 GitHub Actions 配置大致是这样的结构,
yaml
name: FastAPI CI
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run Tests
run: pytest
每次代码推到 main 分支,GitHub 就会拉起一台干净的 Ubuntu 虚拟机,装好 Python,跑一遍依赖安装和测试,全程不需要人插手 。配套的测试代码往往就是这样简单的几行,
python
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_home():
response = client.get("/")
assert response.status_code == 200
如果测试失败,部署直接停下,这正是我们想要的效果,宁可慢一点,也不能让带病的代码流进生产环境 。
第二步,代码质量关卡不能省
测试跑过只说明功能对,代码写得规不规范是另一回事。社区里比较成熟的模板会在测试之前或者同步加上一整套静态检查,常见搭配是 Black 负责格式化,Flake8 抓 bug 和不规范写法(配合 flake8-docstrings、flake8-bugbear 等插件),MyPy 做类型检查,外加 pre-commit hooks 在本地提交前就把问题挡下来 。一套完整的 CI/CD 模板项目还会引入语义化版本控制和 Conventional Commits 规范,把每次提交的类型(feat、fix、docs 等)标注清楚,方便自动生成 CHANGELOG 和触发版本号自动递增 。
第三步,处理好敏感信息
数据库连接字符串、API Key 这类东西,绝对不能直接写进代码仓库。GitHub 提供了 Repository Secrets 机制,专门存放这些敏感配置,流水线运行时通过环境变量读取,代码里只留一个占位符 。这一步说起来简单,但新手最容易在这上面栽跟头,明文密码提交上去,删了历史记录也未必彻底清干净。
第四步,构建镜像并推送
测试和检查都通过之后,才轮到构建 Docker 镜像。FastAPI 官方给出的 Dockerfile 范例大致遵循这个思路,先装依赖,再拷代码,用 CMD 的 exec 形式启动 Uvicorn,这样容器收到停止信号时能正确传递给 Python 进程,不会出现僵死进程 。镜像构建完之后推送到镜像仓库,AWS 的 ECR(Elastic Container Registry)是不少团队的选择 。
第五步,部署上线
部署环节的做法就五花八门了。有开发者分享的实践路径是,GitHub Actions 构建镜像后推到 ECR,再通过 SSH 连进 EC2 实例,拉取最新的 docker-compose.yml 完成更新 。更讲究一点的团队会追求零停机部署,也就是新旧版本切换时用户完全感知不到中断,常见做法是配合负载均衡器,先起新容器做健康检查,确认没问题再把流量切过去,旧容器随后优雅退出 。
🚦 生产环境的几个关键考量
流水线跑通只是第一步,真正上了生产环境还得盯着几件事。
进程模型的选择很关键。单独用 Uvicorn 虽然启动快,但生产环境更推荐 Gunicorn 管理多个 Uvicorn worker 进程,这样单个 worker 崩了不会拖累整个服务,Gunicorn 还负责进程的健康监控和自动重启 。FastAPI 官方文档也专门讨论了副本数量(replication)的问题,到底是用一个负载均衡器配多个 worker 容器,还是每个容器只跑一个进程,取决于具体的资源和运维习惯 。
环境变量和配置管理 也别偷懒,.dockerignore 文件该写就写,避免把 .git、虚拟环境这些不必要的东西打进镜像里,镜像体积和构建速度都会受影响 。
监控和可观测性这块,成熟的模板会集成结构化日志(比如用 structlog)和 Prometheus 指标采集,方便后续排查问题和做容量规划 。
下面这张表大致总结了一条完整流水线里各个环节常用的工具选择。
| 环节 | 常见工具 | 作用 |
|---|---|---|
| 版本控制与触发 | GitHub Actions / GitLab CI | 监听代码推送,自动触发流水线 |
| 依赖管理 | Poetry / pip | 锁定依赖版本,保证环境一致 |
| 代码质量 | Black、Flake8、MyPy | 格式化、静态检查、类型校验 |
| 测试 | pytest + TestClient | 单元测试与接口测试 |
| 容器化 | Docker | 打包应用及运行环境 |
| 镜像仓库 | AWS ECR / Docker Hub | 存储与分发镜像版本 |
| 部署编排 | Docker Compose / Kubernetes | 管理容器的启动与更新 |
| 进程管理 | Gunicorn + Uvicorn | 多进程管理,提升生产环境稳定性 |
💡 写在最后
FastAPI 的 CI/CD 生态其实没有官方标准答案,更像是社区在 GitHub Actions、Docker、pytest 这几块基石上,各自搭建出适合自己团队的组合。对个人项目或者小团队来说,一条简单的测试加构建加部署的三段式流水线足够应付日常需求。对追求高可用的生产系统而言,零停机部署、多进程管理、监控告警这些环节就绕不开了。说到底,CI/CD 不是为了炫技,而是为了让代码从提交到上线这段路走得又快又稳,把人为失误的空间尽可能压缩到最小。
参考资料
Deploy FastAPI Like a Pro, GitHub Actions, GitLab CI, and Zero-Downtime Reloads, Medium medium.com/@diwasb54/d...
gsinghjay/fast-api-ci-cd, GitHub Repository, FastAPI Full Stack with CI/CD Template github.com/gsinghjay/f...
CI/CD for FastAPI, From Your First GitHub Action to Production-Ready DevOps, DEV Community dev.to/charan_gutt...
FastAPI in Containers - Docker, FastAPI Official Documentation fastapi.tiangolo.com/deployment/...
Production-Ready FastAPI Deployment Using Docker and Uvicorn, Seenode seenode.com/blog/deploy...
What is the right way to deploy a FastAPI app?, Reddit r/FastAPI www.reddit.com/r/FastAPI/c...
Testing, FastAPI Official Documentation fastapi.tiangolo.com/tutorial/te...
Is this really what I have to do to test?, Reddit r/FastAPI www.reddit.com/r/FastAPI/c...
Testing FastAPI the Right Way, pytest, Fixtures, and Dependency Overrides, Level Up Coding levelup.gitconnected.com/testing-fas...