首页/开发/CI/CD 与发布速查/一次构建、多环境部署(Build Once, Deploy Many)
流水线设计54 条

一次构建、多环境部署(Build Once, Deploy Many)

同一份不可变制品从测试环境一路晋级到生产,避免「每环境重新构建」带来的行为漂移与不可回滚。

CI/CD 与发布速查开发更新于 2026-10-13

一次构建多环境是什么意思

同一份不可变制品从测试环境一路晋级到生产,避免每个环境重新构建带来的行为漂移与不可回滚。原则是:制品在验证过的二进制或镜像上原样晋级,环境差异只体现在运行时配置(环境变量、配置中心、挂载文件)。落地常见做法是按摘要(digest)引用镜像,各环境引用同一 sha256,而不是各自重新构建;回滚只是把旧制品重新部署,验证结论有据可依。它与 12-Factor 的配置分离、与渐进式交付都是配套关系:制品唯一、配置外部化,晋级与回退才有确定对象。

基本信息

原则制品在验证过的那个二进制或镜像上原样晋级
落地按摘要(digest)引用镜像,用同一构件的晋级而非重建
收益回滚只是把旧制品重新部署,验证有据可依
配置边界环境差异放运行时配置,不进构建产物
传递方式镜像仓库按摘要,包库按不可变版本号
关联原则与 12-Factor 配置分离配套,制品唯一才有可回滚

典型使用场景

  • 多环境晋级链:同一镜像逐级提升到预发、生产,每级做的只是部署与审批。
  • 合规审计:监管要求可追溯生产运行的是哪个提交,摘要与提交一一对应。
  • 回滚设计:回退到上一版本就是重新部署旧制品,不必重建当时可能已无法重现的依赖。
  • 并行环境:预览环境与金丝雀环境都引用同一制品,行为差异只来自配置。
  • 多区域部署:同一摘要分发到多个区域,避免区域间构建差异。
  • 紧急修复:修复构建一次,测试与生产用同一份,缩短验证到上线的链路。
  • 成本优化:构建一次多环境使用,省去重复编译的时间与算力。
  • 事故复盘:能明确部署的是哪份制品,定位根因不靠猜版本。

按摘要晋级

按摘要晋级
docker build -t registry.example.com/app:1.8.0 .  # 只在流水线构建一次
docker push registry.example.com/app:1.8.0  # 推入制品库
# 取内容摘要(部署引用它,标签只作人类可读别名):
docker inspect --format '{{index .RepoDigests 0}}' registry.example.com/app:1.8.0
# 各环境引用同一摘要(推荐),而不是各环境重新 build:
docker pull registry.example.com/app@sha256:<digest>
kubectl set image deploy/app app=registry.example.com/app@sha256:<digest>

反模式速查

反模式后果替代做法
每环境重新构建同版本行为漂移按摘要晋级
构建参数写死环境值制品绑定单一环境改运行时注入
latest 浮动标签晋级新旧内容不一致版本标签加摘要
生产现场手工改文件制品与仓库不一致热修改回仓库重发
若生产环境重新编译或重新打包,测试结果不再代表生产运行内容,制品库里的验证记录也失去意义。
摘要由镜像内容计算:同一镜像的多个标签共享同一摘要,按摘要晋级可以完全绕开标签被覆盖的风险。
不追求摘要级严格也可以:小团队至少做到同一制品文件从测试传到生产,避免各环境各自打包。关键是验证对象与发布对象是同一份。

易错点

  • 生产构建参数不同(如构建参数写死环境值)导致同一版本不同行为:环境差异应放到运行时配置。
  • 用浮动标签 latest 晋级:新旧环境引用的实际内容可能不一致,回滚不可靠,应锁摘要或不可变版本标签。
  • 测试与生产的制品来源不同(不同分支各自构建):验证结论无法迁移,测试通过只是心理安慰。
  • 没有制品库、只靠 CI 缓存保存产物:缓存被清理后无法重建发布对象,发布与回滚同时失效。
  • 临时热修直接改生产环境文件:产生环境漂移,下次发布又被覆盖回去,应把热修改回仓库重新走制品流程。
  • 把配置打进镜像再为每个环境重建:等于回到每环境构建,还制造出多份几乎相同又互相混淆的镜像。

数据来源与参考

  • Humble & Farley《Continuous Delivery》
  • Docker Docs《Registry》
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌