返回文章列表

迁到 Coolify 之后,我又给部署补上了版本验证和回滚

2026年10月12日


今年三月,我写过一篇迁移到 Coolify 的记录。当时最直接的收益,是把服务、证书和日志放到一个可管理的地方,减少手工 SSH 操作。

几个月之后,我继续维护五个落地页,开始补另一层能力:这次上线的到底是哪一版?如果不对,怎么退回发布前的那一版?

点下 Redeploy 很容易。把这两个问题回答清楚,需要更多证据。

部署方式后来也变了

旧文章记录了当时的服务器构建,以及计划中的自动化。现在这五个落地页的流程是:

本地已验证代码
    ↓
本地构建 Docker 镜像
    ↓
推送 GHCR
    ↓
通过认证接口触发 Coolify
    ↓
核对线上版本与实际文件

Coolify 里的运行 Dockerfile 使用 GHCR 的镜像。本地承担主要构建工作,服务器负责拉取和运行。

目前这条发布路径由本地脚本显式执行,GitHub Actions 自动发布尚未启用。读旧文章里的操作方式时,需要把它看作当时的记录。

latest 很方便,也很难回答问题

latest 是一个会移动的标签。昨天和今天拉取它,得到的镜像可能不同。

只记录“发布了 latest”,无法定位一个具体版本。因此现在发布时,会同时推送 latest 和 Git 短提交号标签。

但我没有只依赖标签。镜像标签和容器实际运行的文件,是不同层次的证据;页面 HTTP 200 也只能说明它能响应,不能单独证明新代码已经上线。

官网现在会把构建提交号写进页面的 build-sha 元信息。发布脚本等待并核对它,而不是看到首页返回 200 就结束。

其他四个产品站目前还没有同样的元信息,脚本使用首页内容变化作回退判断。本次发布又额外检查了实际容器的文件层、首页哈希以及新图片文件,不能把四站的判断方式写成已经与官网完全相同。

先备份旧镜像,再构建新镜像

以前想回滚时,很容易先想到“找到旧提交,再构建一次”。

问题是旧提交重新构建,不一定得到发布前正在运行的东西。依赖下载、基础镜像和外部资源都可能改变,构建时网络也可能不可用。

现在的落地页脚本会在发布前保存当前 latest 的镜像备份,命名为:

backup-pre-<本次提交号>

这份备份记录的是发布前的镜像。备份遇到无法确认的错误时,发布会停止,不能把网络错误当成“没有旧镜像”。

回滚入口也使用这份备份,而不是必须重新跑完整构建:

bash script/deploy/deploy_landing.sh gunlabs --rollback backup-pre-fd20178a

这里的标签对应本次已完成的发布。执行回滚仍然是一次生产变更,需要检查目标和当时状态。

发布前的约束,也写进脚本

现在脚本会检查工作区是否干净,当前提交是否等于远端 master,Docker 是否可用,以及是否已有另一场发布占用锁。

这些检查的目的很具体:避免发布本地未提交的内容、未合并的功能分支,或者两场同时更新同一个镜像标签的部署。

本机负载也有门槛。开始发布前,负载需要低于 12;一次只发布一个站。

我没有让脚本在构建中途因为负载升高就杀掉发布。它在开始时决定能否启动,之后采样并记录峰值。

这个规则来自实际使用方式:本机还可能跑 Flutter 和 Xcode。开始前等待资源合适,比在镜像推送或切换途中突然中断更容易处理。

最小权限之后,要准备另一条验证路径

部署令牌可以触发发布,不一定有读取部署队列的权限。

这次就遇到了状态读取返回 403 的情况。脚本改为轮询线上内容,没有为了方便查询而直接扩大令牌权限。

但内容变化也不是所有检查的终点。最终我又通过已有管理入口只读核对了五个部署任务,确认它们都是 finished。

触发发布、观察页面和读取运行状态,是三种不同操作。把权限与验证方式分别安排好,流程才不会卡在“按钮按下去了,但结果不知道”。

外部下载依然可能阻止发版

这次设备截图优化通过测试之后,生产构建还曾因为 Google 字体下载的 TLS 连接中断而失败。网络恢复后,又遇到过字体地址解析错误,后续完整构建才成功。

因此,单独下载一个字体文件成功,不能替代完整生产构建;本地测试通过,也不代表镜像已经可以发布。

我保留了失败日志,等待实际构建成功,没有关闭 TLS 校验,也没有用假的字体响应把验收变绿。

这部分仍然是当前流程的依赖:未来构建需要可用的外部下载网络。

这次五站发布核对了什么

10 月 12 日,五个站点逐站发布了 fd20178a。发布后的检查包括:

  • 五个 Coolify 部署任务均为 finished。
  • 线上静态资源、文章与其他页面可访问,缺失路径返回 404。
  • 72 张新合成图与仓库文件逐字节一致。
  • 运行镜像文件层匹配发布标签,容器首页哈希匹配公网响应。
  • 五份旧镜像备份的文件层匹配发布前实际生产镜像。
  • 三个视口的线上浏览器检查通过。

这次没有执行实际生产回滚。备份匹配检查,和把生产真的切回去,是两个不同的验收范围。

落地页的镜像备份流程,也不能直接等同于带数据库的 Server 回滚方案。数据库结构、写入数据和凭据需要另行考虑。

Coolify 仍然帮我管理容器。新增的脚本和核对步骤,则让我能把一次发布描述成一个具体版本、一组验证结果,以及一个已保存的回退目标。


查看所有文章

本站展示个人独立开发的产品与技术实现过程。技术交流或对产品有反馈,请邮件联系。

© 2026 GunLabs · 刘罡 · 桂ICP备2025072478号-3 · 隐私政策