FastAPI 后端 Docker + GHCR + GitHub Actions 自动部署实践

总结一次将 FlyingrtxFast 后端 Docker、GHCR、GitHub Actions 与服务器 Docker Compose 部署链路打通的实践,梳理关键配置思路、关键配置清单与典型排障要点。

FastAPI 后端 Docker + GHCR + GitHub Actions 自动部署实践
目录

FastAPI 后端 Docker + GHCR + GitHub Actions 自动部署实践

作者:文文

前言

在给 FlyingrtxFast 做后端部署时,我希望把这条链路打通:

  • 本地提交代码
  • GitHub Actions 自动构建 Docker 镜像
  • 镜像推送到 GHCR
  • 服务器自动拉取镜像并通过 Docker Compose 重启服务

目标很直接:把后端发布从手工操作改造成可重复执行的标准流程。

这篇文章主要整理这次实战中的部署结构、关键配置思路,以及几个典型问题的排查结论。


一、最终部署链路

最终落地后的链路如下:

本地开发 -> git push -> GitHub Actions
         -> 构建 backend Docker 镜像
         -> 推送到 GHCR
         -> SSH 到服务器
         -> docker compose pull / up -d
         -> 宿主机 Nginx 转发到 backend 服务

核心组件只有四个:

  • Docker
  • GitHub Actions
  • GHCR(GitHub Container Registry)
  • 服务器上的 Docker Compose

这套组合的优点很明确:

  • 服务器不再承担复杂构建逻辑
  • 部署链路清晰,职责边界明确
  • 后续更容易做回滚、多环境扩展和服务拆分

二、后端容器化基础

要实现自动部署,前提是后端能够稳定打包成镜像。

这次补齐的基础文件包括:

  • backend/Dockerfile
  • backend/.dockerignore
  • backend/docker-compose.yml
  • backend/.env.example

其中最核心的是 Dockerfile。简化后的思路如下:

FROM python:3.12-slim AS builder

WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY . .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "59888"]

这里采用多阶段构建,主要是为了:

  • 分离构建环境与运行环境
  • 减少最终镜像体积
  • 保持镜像结构更清晰

而 docker-compose.yml 的职责,则是在服务器上以统一方式启动和管理容器。


三、GitHub Actions 工作流设计

自动部署真正跑起来,关键在 workflow。

这条链路的核心步骤可以概括为四步:

1. 检出代码

- uses: actions/checkout@v4

2. 登录 GHCR

- uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

3. 构建并推送后端镜像

- uses: docker/build-push-action@v6
  with:
    context: ./backend
    file: ./backend/Dockerfile
    push: true

4. 通过 SSH 到服务器执行部署命令

服务器侧部署逻辑保持尽量简单:

  • 登录 GHCR
  • 拉取最新镜像
  • 执行 docker compose up -d

这样可以把部署动作压缩为一套稳定、可重复执行的命令,而不是依赖人工逐步操作。

关键配置清单

如果要把这套链路真正跑通,至少要先准备好下面这些配置:

  • GitHub Actions Secrets:GITHUB_TOKEN、服务器 SSH 私钥、服务器地址、部署用户名
  • 镜像仓库权限:确认目标仓库允许 CI 推送,服务器也能正常拉取镜像
  • 服务器运行环境:已安装 Docker、Docker Compose,并具备镜像拉取权限
  • 部署目录文件:至少包含 docker-compose.yml、.env 或 .env.example
  • 反向代理链路:宿主机 Nginx 已正确转发到后端服务端口

如果这几项没有先准备好,workflow 即使运行,也很容易卡在登录仓库、拉镜像、端口冲突或容器无法启动这些环节。


四、服务器侧职责划分

在这套方案里,服务器只负责三件事:

  1. 保存运行时 .env
  2. 拉取镜像
  3. 用 Docker Compose 启动容器

这种职责划分的好处是:

  • 不需要服务器每次都 git pull
  • 不需要服务器本地重新安装和构建 Python 依赖
  • 线上运行环境更容易保持一致

服务器只接收已经构建好的镜像,部署速度和环境可控性都会更好。


五、环境变量处理方式

这次部署里,环境变量分为两类。

1. 构建与部署阶段变量

例如:

  • 镜像名
  • GHCR 用户名
  • GHCR Token
  • 服务器地址
  • SSH 私钥

这类变量适合放在 GitHub Actions Secrets 中。

2. 应用运行时变量

例如:

  • 数据库连接
  • JWT_SECRET
  • COS 配置
  • 第三方 API Key
  • 域名配置

这类变量不应该写进镜像,而应该由服务器上的 .env 提供。

因此,实际运行时容器中的业务配置来源是服务器部署目录下的 .env 文件。
workflow 可以同步 .env.example,但不应该在每次部署时强行覆盖现有 .env。


六、实战中踩到的几个典型问题

这条链路并不是一次就跑通的。真正排查下来,比较典型的问题主要有三个。

1. Docker 问题不一定是业务代码问题

部署阶段最容易出现的误判是:只要容器起不来,就先怀疑代码。

但很多问题其实发生在更外层,例如:

  • 端口被占用
  • Docker 状态异常
  • 容器名冲突
  • 配置文件挂载不正确

更合理的排查顺序应该是:

  1. 查看容器状态
  2. 查看容器日志
  3. 查看 docker inspect
  4. 最后再怀疑业务代码

这个顺序很重要,能明显减少排障绕路。

2. 宿主机端口规划必须提前设计

后续在尝试多容器结构时,曾将容器 Nginx 映射到宿主机 18080,结果容器一直无法启动。

最后定位到的根因并不是 Nginx 配置错误,而是宿主机端口冲突:

address already in use

这类问题在 Docker 部署中很常见。表面看像是容器异常,实际只是宿主机端口已经被其他进程占用。

所以部署方案里,端口职责一定要先设计清楚。

3. GitHub Actions 能连服务器,不代表链路一定正确

自动部署的后半段依赖 SSH/SCP,这一段常见问题包括:

  • SSH 端口配置错误
  • 安全组未放通
  • GitHub Runner 无法访问服务器
  • 私钥与公钥不匹配

其中一个常见误区是:

  • 本地机器可以 SSH 登录服务器
  • 不代表 GitHub Actions Runner 也一定可以访问

因为 Runner 运行在公网环境,它和本地网络条件完全不同。这一点在自动部署排障时必须单独考虑。


七、这套链路打通后的价值

这套自动部署跑通后,最大的变化有三点。

1. 发布动作从人工操作变成标准流程

原来的发布方式往往是:

  • 登录服务器
  • 拉代码
  • 手工调整
  • 手工重启

而现在变成:

  • 提交代码
  • push
  • 等待 workflow 完成

部署动作被标准化之后,重复劳动会明显减少。

2. 发布过程更容易追踪

每次部署都可以对应到:

  • 某次提交
  • 某个镜像 tag
  • 某次 workflow run

当线上出现问题时,回看、定位和回滚都会更方便。

3. 为后续扩展打下基础

虽然这次重点只是把单后端自动部署打通,但链路建立起来之后,后续继续扩展会轻松很多,例如:

  • 多后端拆分镜像
  • 多环境部署
  • 更细的回滚策略
  • 更清晰的服务边界

自动部署的意义不只是节省操作时间,更重要的是让交付过程开始具备工程化基础。


八、经验总结

如果把这次实践压缩成几条最值得保留的结论,我会总结为:

  1. 服务器尽量只负责拉镜像和启动,不承担复杂构建逻辑。
  2. 运行时配置放在服务器 .env,不要写进镜像。
  3. GitHub Actions + GHCR + Docker Compose 是一套适合中小项目的自动部署组合。
  4. 排障时先检查端口、容器状态、挂载和网络,再去怀疑业务代码。
  5. 先把单服务自动部署跑通,再考虑复杂架构演进。

结语

这次把 FlyingrtxFast 后端 Docker + GHCR + GitHub Actions 自动部署真正打通之后,最大的变化不是“部署更方便了”,而是整个发布过程开始有了清晰边界和统一方式。

很多时候,自动部署并不是锦上添花,而是项目进入稳定工程化阶段的重要一步。

如果你还在手工传代码、手工重启服务,那么尽早把下面这四件事补齐,部署这件事就能先稳定下来:

  • 能构建
  • 能推镜像
  • 能自动拉起
  • 出问题能排查

把这四件事做好,后续再扩展复杂架构,成本会低很多。


文文,2026 年 3 月

相关文章

技术 · 2026-03-21GitHub Actions 自动部署里的 SSH Key 是什么?公钥私钥怎么用?一篇讲透技术 · 2026-03-16如何用 Docker 打包部署你的应用?一篇文章搞定 Docker 的所有核心概念技术 · 2026-03-16用 Python FastAPI 构建高性能 REST API:从零到一的完整指南