核心观点 部署方式不混用:本机一个入口,服务器只有容器编排与几件部署资产;镜像本机构建后传输,tag 是 git SHA,禁止 latest。迁移不是框架送的,要自己做并固定发版顺序。每次生产发版在发布记录里加一行。运维靠开关而不靠发版:打开有顺序,止损不发版。
CLAUDE.md 规则 10 只有一句话:「部署方式不混用。」展开是四条:

本机构建、盖上 SHA、传到服务器;服务器上没有扳手,latest 那张标签在地上。
为什么这么严?因为混用的代价是「两个环境跑的不是同一个东西」。服务器上 git pull 再构建,构建结果取决于服务器的工具链版本、网络、缓存;本机构建后传输,构建结果只取决于那个 SHA。镜像是不可变制品:同一个 SHA 构建一次,预发验过就原样提升,不重新构建。
dev.ps1 build 出三个镜像(api、web、执行容器),脏工作区会拒绝构建;dev.ps1 ship 把镜像与五件资产送到服务器,不传环境变量文件。发版之后还要做一件事——ship 收尾会提醒:记 docs/releases.md。
R-BUN 暴露了一个本来会卡死上线的问题:框架的自托管镜像不执行数据库迁移。空库直起,健康检查回 200,触库的端点全部 500。任务卡的原话:「实测,空库直起则 /health 200 但触库端点 500。」
所有者裁定的方案是自己写迁移脚本:SQL 从被部署的镜像里取,版本记录表与框架同构,单事务,幂等,带 advisory 锁防并发。审查在这个脚本上抓了好几条:参数要过白名单、环境变量文件不能作为 shell 执行、SHA 硬校验、迁移版本唯一性与数值排序。
有了脚本,发版顺序就固定了:
部署文档解释了为什么顺序不能颠倒:健康检查不触库,「先起全部再迁移」会留下一段中间状态——反代已经对外放流量,容器 healthy,健康检查全绿,而真实业务接口全部 500。这段窗口靠监控发现不了,只能靠部署顺序消除。升级同理:只对数据库等待 healthy 时,旧版 api 还在跑、还在对外服务,迁移是在它脚下改 schema。用短暂停机换确定性。
回滚也简单:镜像即回滚单元,把环境变量里的 IMAGE_TAG 换回上一个 SHA 再起。涉及不可逆迁移时先恢复备份。
docs/releases.md 是投产后所有者裁定的硬要求:「每次生产发版在这里加一行,不成轮次的小修补也不例外。」
一行七列:日期、SHA、迁移版本、内容、环境变量与部署资产变更、回滚点、留证。到 2026-09-04 七行:
| 日期 | 内容 | 记下的教训 |
|---|---|---|
| 09-02 | 首发 | 漏了一个环境变量项,补后重建 api;compose 缺 udp 端口映射,HTTP/3 广告出去却连不上 |
| 09-02 | 生图工具 + 公式渲染修补 | 生图的域白名单是另一份清单,环境变量要再写一次 |
| 09-02 | 两条纯前端修补 | 无部署资产变更,迁移无待执行 |
| 09-03 | tab 呈现开关 + 构建修复 | 新服务漏补进构建白名单,按前一个提交构建会整站 500 |
| 09-03 | Skills 技能库 1.0 | 反代配置有变更,重传后 validate 加 reload,不重启容器;发版时库里还没有任何 skill,是空态 |
| 09-03 | 一次发三轮 | 新增执行容器;发版时双闸关闭,当日按顺序打开 |
| 09-04 | 读网页 skill | 新增出网容器与专用网络;第五件部署资产;零迁移零前端改动 |
每一行都有「回滚点」——服务器上仍保留的上一个镜像 tag——和「留证」——冒烟结果:几个端点非 404、管理面工具数、运行时判据、协议判据、哪条流用真实对话验过、原始字节里搜过哪些字符串零命中。
发布记录里还有几段独立的小节,记那些一句话说不清的坑:合并轮次分支后发版第一步是重新安装依赖;SSH 传输密集重连会把自己关在门外;某次构建修复到底修了什么。它们放在发布记录里而不是别处,因为下次发版的人一定会看这个文件。
投产之后,「放开一种能力」这件事尽量不靠发版,靠开关:

工具闸、skill 闸、环境变量闸,加一个不需要重新部署的 STOP。
打开有顺序。 R-SKILLS-2 的能力发版时是关着的,当日按五步打开:对齐库内展示副本与代码副本(哈希不一致不会被注入);打开加载工具的闸;逐个打开 skill 并确认一致性状态;服务器环境变量加解锁项并重建 api;最后打开运行工具的闸。每一步有判据,每一步可以停。
止损不发版。 管理面关掉运行工具,当场停用;关掉一个 skill,单个下线;停掉执行容器,该 skill 的调用以固定文案失败、其它照常。R-WEBFETCH 发版当天实测:停容器后调用 3 毫秒快速失败,起回来立即恢复。
环境变量变了要重建容器。 restart 不生效,要 up -d 重建。这条在部署文档、任务卡、CLAUDE.md 三处都写了,因为它的表现是「改了没生效」而不是报错。
别在 auto 模式做「关掉 → 验证 → 开回来」。 实现 agent 在自动模式下能关掉一个工具,但「在生产打开 agent 工具」这一类动作会被安全分类器拦下,于是生产被留在半开状态一轮。教训:这类运维先请所有者切模式再动手。
站点没有后台界面。所有写操作——内容发布、配置、工具启停、tab 开关——都走一个无状态的管理协议端点,由所有者用客户端操作。它同时是运维面。
几条运维口径:
生产服务器在境内,这个事实影响验收:
预发环境的角色也变了:上线前它是必经的,上线后所有者裁定为可选项。130 与生产的 SHA 允许不一致,需要时先在预发验,不需要就直接发生产。
所有者 2026-09-03 裁定的三条:
还有一条纪律来自所有者的当场纠正:镜像构建放在审查收口、分支合并之后。 审查一旦要整改,SHA 就变,镜像必须重打——审查没过就打镜像是浪费。审查期间只做本机检查、测试和页面实测。
服务器上构建。 结果取决于服务器状态,不可复现。
用 latest。 回滚时不知道上一个是什么。
先起服务再迁移。 健康检查全绿、业务全 500 的窗口。
改了环境变量只 restart。 看起来没生效。
发版不记录。 三天后不知道生产跑的是什么、上一个是什么。
审查没过就构建。 白打一次镜像。
为自己的项目写发布记录的表头(日期、版本标识、迁移、内容、资产变更、回滚点、留证)和发版顺序(每一步写清能不能停、停了往哪回)。然后列出所有「放开一种能力」的动作,看哪些能改成开关而不是发版。