运维与升级¶
本页是 Turbo EA 生产环境的运维指南:升级和数据库迁移如何工作、如何备份和回滚、建议运行哪些环境,以及大规模运行时容易踩到的坑。
生产镜像与版本锁定¶
发布在 ghcr.io/vincentmakes/turbo-ea/* 的镜像是运行生产环境的推荐方式——标准的 docker-compose.yml 默认拉取这些镜像,而从源码构建属于开发工作流。除了方便之外,发布的镜像还带有本地构建所不具备的供应链保障:每次发布都是多架构的(amd64 + arm64),使用 cosign 签名(无密钥 OIDC,可对照 GitHub Actions 工作流身份进行验证),并附带 SLSA 来源证明和 SBOM。镜像在发布时会因严重 CVE 被拦截,上线后每天重新扫描,并每周基于最新的 Alpine 仓库重新构建,因此基础镜像补丁会自动流入。如果贵组织在准入时强制执行镜像签名验证,cosign 签名可以直接接入——验证命令见供应链。
最重要的习惯:锁定你的版本。:latest 标签只在发布版本和每周重建时被重新指向——不是每次提交都会更新——因此它可能按照你无法控制的节奏发生变化。在 .env 中设置一个明确的标签:
TURBO_EA_TAG=2.23.1
基础用法见锁定版本,完整的标签树和预发布渠道策略见版本发布。
托管 PostgreSQL¶
在能够使用托管 PostgreSQL 服务的企业环境中——Azure Database for PostgreSQL、Amazon RDS / Aurora、Google Cloud SQL 或同类产品——让 Turbo EA 直接使用该服务是推荐的配置。自带的 db 容器只是一个零依赖的默认选项,并非必需:通过 POSTGRES_* 变量把后端指向你的实例,并跳过自带服务即可(见使用现有 PostgreSQL)。
托管服务替你承担的事情:
- 备份与时间点恢复(PITR)——自动化、保留期受管、可恢复到任意时刻,正是下文回滚策略所需要的。
- 高可用与故障转移——可用区或跨区域冗余,无需自行运维复制。
- 引擎补丁、静态加密、网络隔离——按贵组织的合规基线处理(私有终结点、IAM 集成)。
三件不会改变的事:后端在启动时仍会自行执行 Alembic 迁移(本页的升级模型完全相同);backend_data 卷仍需要单独备份(文件附件和扩展不存放在 PostgreSQL 中);SECRET_KEY 的保管责任仍在你。自带镜像搭载 PostgreSQL 18——你的服务商提供的任何较新的主版本都可以。
升级如何工作:Alembic 迁移¶
数据库模式的兼容性由 Alembic 自动处理。后端在启动时执行 alembic upgrade head,因此当前模式与新版本之间所有待执行的迁移都会——按顺序——在应用开始提供服务之前完成。
迁移按顺序编号且是累积的,这意味着跨版本升级是安全的:例如从 2.10 升级到 2.23,所有中间迁移都会依次执行。你不需要逐个经过每个次要版本。
几个值得了解的行为:
| 场景 | 启动时会发生什么 |
|---|---|
| 全新数据库 | 直接创建所有表并将数据库标记为 head——不会重放迁移。 |
| 已有数据库 | 待执行的迁移会在 API 可用之前自动运行。 |
RESET_DB=true |
所有表被删除、重建并重新填充种子数据。切勿在生产环境设置。 |
在同一个主版本线内,迁移保持增量式且升级向后兼容——完整的约定见兼容性策略。
切勿用旧版后端运行新版模式
Alembic 在启动时只向前迁移。旧代码面对更新的模式属于未定义行为——这是回滚的关键约束(见下文)。
升级流程¶
- 阅读变更日志。 查看当前版本与目标版本之间的
CHANGELOG.md条目。不兼容的变更会提升主版本号。 - 备份数据库和数据卷(见下文)。
-
提升标签并拉取:
TURBO_EA_TAG=2.24.0 docker compose pull docker compose up -d -
观察启动日志,确认迁移在 API 开始提供服务之前顺利完成:
docker compose logs -f backend
维护窗口
迁移通常很快,但在大型清单上,某些数据迁移可能需要几分钟,期间后端不提供服务。请在维护窗口内安排升级。
备份¶
每次升级前都要备份,并且无论如何都应自动化每晚备份:
docker compose exec db pg_dump -U turboea turboea > backup-$(date +%F).sql
如果你修改过 POSTGRES_USER / POSTGRES_DB,请相应调整用户名和数据库名。对 postgres_data 卷做快照是等效的替代方案。若使用托管 PostgreSQL 服务(见上文「托管 PostgreSQL」一节),应优先使用服务商的自动备份和时间点恢复,而不是手工转储——不过偶尔做一次 pg_dump 作为可移植、不依赖服务商的副本仍然值得。
同时备份 backend_data 卷——它保存着文件附件、已安装的扩展和工作区传输包,这些都不存放在 PostgreSQL 中。
关于恢复能力还有两点:
- 定期测试恢复。 从未被恢复过的备份只是一种希望,而不是一个方案。
- 归档的卡片是软删除的,在永久清除前有 30 天的窗口——这是针对数据失误的安全网,与基础设施恢复是两回事。
回滚与恢复¶
在生产环境中,模式迁移实际上是只进不退的:虽然 Alembic 技术上支持降级,但携带数据的迁移并不总能无损逆转,而且应用从不自动执行降级。可靠的回滚策略是:
- 停止整个服务栈。
- 恢复升级前做的数据库备份(托管 PostgreSQL:时间点恢复到升级前的那一刻)。
- 将
TURBO_EA_TAG改回上一个版本。 docker compose up -d——恢复后的数据库与旧代码的模式匹配,一切保持一致。
切勿只回滚镜像
只回滚镜像却保留已迁移的数据库,是自动迁移系统唯一无法保护你的组合。数据库备份和镜像标签必须一起变动。
环境与发布治理¶
对大多数组织而言,两套环境(预发 + 生产)就足够了,因为升级用的是厂商发布的镜像,而不是自定义构建——你在做验证,不是在做开发。只有在构建自定义扩展或重度集成时,完整的 Dev/SIT/UAT/Prod 链路才更有价值。
| 环境 | 用途 | 说明 |
|---|---|---|
| 开发 / 沙箱(可选) | 试验元模型变更、演示 | SEED_DEMO=true 加载演示数据集;RESET_DB=true 提供全新起点。 |
| 预发(Staging) | 优先验证新版本 | 数据接近生产;最先接收新标签。 |
| 生产 | 锁定标签、备份、维护窗口内升级 | 永远不用 latest,永远不用 RESET_DB。 |
把真实数据引入预发环境的两种好方法:
- 工作区传输:将生产工作区导出为
.zip包并导入预发环境。密钥(SMTP、SSO、AI、ServiceNow 凭据)按设计被剥离,绝不离开实例。 - 数据库恢复:把生产的
pg_dump恢复到预发数据库(在托管服务上,克隆或对生产实例做时间点恢复同样很好用)。数据库中的加密密钥派生自SECRET_KEY,因此预发环境要么使用相同的SECRET_KEY,要么在那里重新录入集成凭据。
治理层面:
- 把
.env文件和锁定的TURBO_EA_TAG当作「配置即代码」——保存在内部 Git 中,把升级变成一次经过评审的变更(一个提升标签的 pull request)。 - 由于预发和生产拉取的是同一个锁定的 GHCR 标签,你验证的正是将要晋级的、逐字节相同的制品。
- 先升级预发 → 观察运行几天 → 再把同一个标签晋级到生产。
常见的坑¶
- 不锁定就运行
latest——一次例行的docker compose pull会变成计划外的升级和计划外的迁移,节奏由发布日程决定而不是由你决定。 - 不备份就升级——迁移只进不退;备份就是你的回滚手段。
- 丢失或更改
SECRET_KEY——它既签发 JWT,又派生存储密钥的加密密钥(SMTP、SSO、ServiceNow 凭据)。更改它会让已存储的密钥无法解密。请像对待数据库凭据一样对待它:入库保管、保持稳定、做好备份。 - 环境文件里遗留
RESET_DB=true——它每次启动都会不折不扣地执行字面含义。 - 直接编辑数据库——模式状态由 Alembic 掌管,手工 DDL 会与未来的迁移冲突。数据也一样:请通过 API 或界面操作,以保证权限、审计事件和数据质量重算的正确性。
- 不持久化数据卷——
postgres_data和backend_data必须在容器重建后仍然存在;确认你的快照和备份工具同时覆盖两者。 - 只回滚镜像而不恢复数据库——见上文「回滚与恢复」一节。