在 CI/CD 流水线中“构建”只是第一步如何管理构建出来的产物Artifact才是决定交付效率的关键。一个常见的反模式是在测试环境构建一次在生产环境又构建一次——这不仅浪费计算资源更致命的是两次构建可能产生不同的结果让测试变得毫无意义。本文系统讲解制品管理的核心理念“Build Once, Deploy Anywhere”并深入介绍 JAR/WAR 包、Docker 镜像、Helm Chart 等不同类型制品的版本策略、存储方案和生命周期管理。一、制品管理的核心理念Build Once, Deploy AnywhereBuild Once, Deploy Anywhere 是制品管理的黄金法则在整个 CI/CD 流水线中一个制品只构建一次然后以完全相同的形态依次通过各个环境测试 → 预发布 → 生产 。为什么这很重要正确做法构建阶段生成唯一的、不可变的制品如 JAR 包、Docker 镜像测试阶段使用该制品进行验证部署阶段将同一个制品部署到各个环境只改变配置环境变量、数据库连接等二、制品的类型与存储不同类型的制品需要不同的存储和管理方式 实践建议对于容器化项目Docker 镜像应成为唯一的交付制品。JAR 包只存在于构建阶段最终发布到生产的是镜像而非 JAR 包。三、镜像版本策略让每个版本都可追溯镜像标签Tag的设计直接影响部署的可追溯性和回滚效率。3.1 不可变版本标签推荐每个构建生成一个唯一的、不可变的镜像标签确保可以精确定位到对应的代码版本text使用 Git Commit SHA 作为标签registry.example.com/myapp:abc123def456使用构建编号 时间戳registry.example.com/myapp:build-2025-01-15-1432语义化版本 Commit SHA推荐registry.example.com/myapp:v1.2.3-abc123d优势每个镜像对应唯一的代码版本可精确追溯部署时不会意外覆盖已有镜像回滚时只需指定上一个版本的 SHA3.2 可变版本标签辅助使用除了不可变标签通常还会维护一些“指针”标签指向最新的稳定版本textlatest - 指向最新的稳定版本registry.example.com/myapp:latest环境标签 - 指向当前部署到该环境的版本registry.example.com/myapp:prodregistry.example.com/myapp:staging⚠️ 警告永远不要在生产环境使用 latest 标签部署。因为 latest 指向的镜像会变化你无法确定生产环境运行的是哪个版本的代码。3.3 推荐的综合策略四、镜像构建的最佳实践4.1 一次构建多处部署在 CI 流水线中镜像构建应该只发生一次然后通过不同的标签推送到仓库供各环境使用# GitHub Actions 示例jobs:build:steps:-name:Build and push imageuses:docker/build-push-actionv5with:push:truetags:|ghcr.io/${{ github.repository }}:${{ github.sha }} # 不可变标签 ghcr.io/${{ github.repository }}:latest # 最新标签 ghcr.io/${{ github.repository }}:prod # 生产环境指针deploy-staging:needs:buildsteps:# 部署时使用同一个镜像通过 Commit SHA 引用-run:kubectl set image deployment/myapp myappghcr.io/...:${{github.sha}}-n stagingdeploy-prod:needs:buildenvironment:productionsteps:# 生产环境也使用同一个镜像-run:kubectl set image deployment/myapp myappghcr.io/...:${{github.sha}}-n prod4.2 多架构镜像构建如果应用需要同时支持 x86 和 ARM 架构如 Apple Silicon 开发机、ARM 云服务器可以使用 Docker Buildx 构建多架构镜像-name:Set up Docker Buildxuses:docker/setup-buildx-actionv3-name:Build and push multi-arch imageuses:docker/build-push-actionv5with:platforms:linux/amd64,linux/arm64push:truetags:ghcr.io/${{github.repository}}:${{github.sha}}构建完成后Docker 会自动生成一个多架构 Manifest用户执行 docker pull 时系统会根据自身架构自动拉取对应的镜像。五、制品生命周期管理制品不是“存进去就不管了”。随着项目迭代镜像仓库中的制品会越来越多需要有策略地管理其生命周期。5.1 留存策略5.2 Harbor 自动清理配置Harbor 支持基于规则的自动清理# Harbor 清理策略示例retention:rules:# 保留所有带语义化版本标签的镜像永久-tag_selectors:-kind:doublestarpattern:v*decoration:matchestime_scale:daysamount:0# 0 表示永久保留# 保留最近 30 天的开发版本-tag_selectors:-kind:doublestarpattern:*-dev-*decoration:matchestime_scale:daysamount:30六、小结Build Once, Deploy Anywhere 是制品管理的核心原则确保测试和生产使用完全相同的二进制产物镜像版本策略使用 Commit SHA 作为不可变标签语义化版本用于正式发布环境标签作为指针一次构建在 CI 中只构建一次镜像通过不同标签分发到各环境生命周期管理制定合理的留存和清理策略避免镜像仓库无限膨胀