Skip to content

DevOps 流水线基石:Docker 是 CI/CD 的“交付单元”

在现代软件交付流程中,持续集成(CI)与持续部署(CD)已成为高效、可靠发布的核心实践。而在这条自动化流水线中,Docker 扮演着一个至关重要的角色——它不仅是工具链的一环,更是整个流程的交付单元(Delivery Artifact)

这意味着:一次构建,处处运行。无论是在测试环境验证功能,还是在生产集群灰度发布,所部署的都必须是同一个、不可变的 Docker 镜像。这一原则,正是 DevOps 实现可重复、可追溯、高可信部署的基石。


一、什么是“交付单元”?

传统交付模式中,交付物往往是:

  • 一段 Git 分支(如 main
  • 一个 JAR/WAR 文件
  • 一组 Shell 脚本

这些交付物存在共同问题:它们不包含完整的运行环境。部署时仍需在目标机器上安装依赖、配置环境、执行构建命令,导致“构建两次”的风险——CI 中构建一次,生产部署时再构建一次,结果可能完全不同。

而 Docker 镜像则不同。它是一个自包含、不可变、可移植的软件包,内含:

  • 应用代码
  • 运行时(Node.js、Bun、JRE 等)
  • 系统依赖库
  • 环境变量
  • 启动命令

这个镜像一旦构建完成,其内容就固定不变。无论你将它推送到哪里,docker run 启动的都是完全相同的运行时环境。

因此,Docker 镜像成为理想的“交付单元”:CI 阶段构建出镜像,CD 阶段只需拉取并运行该镜像,无需任何额外操作。


二、Docker 如何支撑 CI/CD 流水线?

一个典型的基于 Docker 的 CI/CD 流程如下:

1. 代码提交触发 CI

开发者推送代码到 main 分支,CI 系统(如 GitHub Actions、GitLab CI、Jenkins)被触发。

2. 构建镜像

CI 环境执行:

bash
docker build -t myapp:${GIT_SHA} .
  • 使用项目根目录下的 Dockerfile 构建镜像。
  • 镜像标签使用 Git 提交哈希(如 a1b2c3d),确保唯一性。
  • 构建过程包括依赖安装、TypeScript 编译、静态检查、单元测试等。

3. 运行测试

在 CI 环境中启动容器进行测试:

bash
docker run myapp:${GIT_SHA} npm test

测试在与生产环境一致的容器中运行,结果更可信。

4. 推送镜像到 Registry

测试通过后,将镜像推送到私有或公共 Registry:

bash
docker push myapp:${GIT_SHA}

此时,该镜像成为“已验证的交付物”,可用于任何环境。

5. CD 流水线拉取并部署

CD 系统(或手动操作)在目标环境执行:

bash
docker pull myapp:${GIT_SHA}
docker stop current-app && docker rm current-app
docker run -d --name current-app -p 3000:3000 myapp:${GIT_SHA}

或通过 Kubernetes、Nomad 等编排系统声明式部署。


三、为何必须以镜像为交付单元?

1. 消除环境差异

传统部署中,预发和生产环境可能因操作系统补丁、库版本、环境变量不同而行为不一致。而使用同一镜像部署,确保了环境一致性贯穿全流程。

2. 实现不可变基础设施

镜像一旦构建,内容不可更改。每次变更都必须重新构建新镜像。这避免了“线上手动修改配置”导致的“配置漂移”问题,使系统状态始终可预测、可回滚。

3. 支持精确回滚

若新版本出现故障,回滚不是“切换分支再部署”,而是直接运行上一个已知良好的镜像:

bash
docker run myapp:abc123

无需重新构建,无需担心依赖变化,回滚速度快且可靠。

4. 提升部署效率

镜像在 CI 阶段已预构建完成,CD 阶段只需拉取和启动,大幅缩短部署时间。尤其在多区域、多集群部署场景下,优势更为明显。

5. 便于审计与追溯

每个镜像标签(如 v1.2.3-a1b2c3d)都关联到具体的代码提交和构建日志,可轻松追溯“哪个版本对应哪次提交”“何时构建”“由谁触发”。


四、最佳实践:如何设计生产级交付流程?

1. 唯一构建源

确保镜像只在 CI 环境中构建一次,禁止在开发机或生产服务器上 docker build

2. 使用内容寻址标签

优先使用 Git SHA 或语义化版本 + SHA 作为标签,避免使用 latest

bash
myapp:1.5.0-a1b2c3d

3. 多阶段构建优化

Dockerfile 中分离构建与运行阶段,减小最终镜像体积,提升安全性和启动速度。

4. 镜像扫描与签名

在 CI 流程中集成安全扫描(如 Trivy、Clair)和数字签名,确保镜像无漏洞、来源可信。

5. 与编排系统集成

在 Kubernetes 环境中,通过 Helm Chart 或 Kustomize 引用特定镜像,实现声明式部署。


五、总结

Docker 之所以被称为 CI/CD 的“交付单元”,是因为它解决了软件交付中最根本的问题:如何确保部署的软件在任何环境中行为一致

通过将应用及其运行环境封装为不可变镜像,Docker 实现了:

  • 一次构建,处处运行
  • 环境一致性贯穿全流程
  • 部署可追溯、可回滚、可自动化

在 TypeScript、Nest、Bun 等现代技术栈的项目中,这种标准化交付模式尤为重要。它让团队从“调试环境问题”中解放出来,专注于业务价值交付。

当你将 Docker 镜像确立为 CI/CD 流水线的唯一交付物时,你就已经迈出了构建高可靠性、高效率 DevOps 体系的关键一步。