跳到主要内容
约 4 分钟3 张卡

可重复交付

可重复交付让已验证的同一产物逐级进入生产。本文负责 Docker 镜像、CI/CD 晋升和交付证据。

1. 面试核心​

先记住这几条,再读正文
  • 产物标识。 镜像 digest 标识内容,tag 可以被重新指向。卡 · 综合题
  • 构建与运行分离。 多阶段构建将编译环境与最终运行环境分离。
  • 同一产物晋升。 CD 晋升同一个 digest,环境配置在部署时注入。
  • 构建凭据。 BuildKit secret mount 将构建凭据临时提供给指定步骤。卡 · 构建缓存与凭据
  • 终止信号。 用 exec 形式的 ENTRYPOINT 直接启动应用,应用才能直接接收终止信号。若入口是脚本,脚本需通过 exec 启动应用。卡 · 容器终止信号

2. 镜像与 digest​

镜像由文件系统层和配置元数据组成。RUN、COPY 等指令可产生文件系统变化。CMD、LABEL 等指令主要修改元数据。

tag 便于阅读,digest 用于精确引用产物。部署记录同时保存源码提交与镜像摘要。基础镜像也按 digest 固定,并定期更新后重测。

.dockerignore 缩小构建上下文。密钥、Git 历史和本地缓存应排除。后续层删除文件仍会保留旧层中的内容。

3. 多阶段构建​

构建阶段使用 JDK、Maven 等工具生成 jar。运行阶段只复制必要产物和运行时。

运行镜像采用非 root 用户,并收紧文件系统权限。临时文件使用明确的可写目录。镜像还需具备应用所需的证书与诊断能力。

4. CI​

流水线从固定提交和工具链开始。执行顺序可以如下:

  1. 校验依赖,完成编译与单元测试。
  2. 执行静态检查、集成测试和契约测试。
  3. 构建镜像,生成 SBOM 与构建来源记录。
  4. 对实际镜像执行冒烟测试和漏洞检查。
  5. 签名并发布通过门槛的 digest。

部署端还需校验签名身份与来源策略。生成签名本身只是交付证据的一部分。生产凭据只授予部署阶段。

5. CD 晋升​

测试、预发与生产使用同一个 digest。配置、Secret 和资源声明在部署时注入。

生产前重新打包会产生另一份二进制。晋升直接使用已验证产物,并记录配置版本。不同环境的集成行为仍需各自验证。

6. 无损替换​

新实例就绪后接流量,旧实例按协议排空。探针与端点传播细节见服务发现。

交付验收还需确认进程正确响应 SIGTERM。任务在宽限期内完成,或保存可恢复检查点。

7. 数据库变更​

镜像回退与数据库变更分开管理。兼容扩展和收缩见架构迁移。

流水线记录迁移版本、执行锁和检查点。重型 DDL 使用独立任务,避免多实例启动时并发执行。

8. 发布策略​

发布策略需绑定业务指标与停止条件。分阶段判断见灰度发布。

回退记录镜像 digest、配置版本与数据兼容状态。失败样本保留日志和 Trace,用于后续定位。

9. 流水线故障演练​

演练仓库不可用、拉取失败和探针持续失败。也要验证数据库已升级后的镜像回退。

失败时流水线停止晋升,保留实际部署状态。从提交、构建、配置到实例的关系应可查询。

10. 构建缓存与凭据​

缓存重用已完成步骤,但构建输入仍需固定。远程下载使用浮动内容时,同一 Dockerfile 会产生不同结果。

BuildKit 用 --secret 提供凭据。Dockerfile 中的步骤可使用 RUN --mount=type=secret。挂载只在该步骤执行时可见。构建命令还需避免复制凭据或打印其内容。

ARG 与 ENV 会暴露在镜像或构建元数据中,不适合传密钥。密钥内容变化本身不会使构建缓存失效。确需重跑时,可使用非敏感版本参数或禁用该阶段缓存。

11. 容器终止信号​

exec 形式直接启动应用:

ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Java 作为容器主进程接收终止信号。应用关闭钩子停止领任务,并等待在途工作结束。

shell 形式会增加 /bin/sh -c 中间进程。该 shell 无义务自动转发应用需要的信号。包装脚本可以用 exec java ... 交出进程位置。排空超过宽限期后,平台会强制终止容器。

12. 常见问题​

12.1 latest 与部署记录​

latest 可指向不同内容。回滚清单应使用明确 digest。易读 tag 可保留作检索辅助。

12.2 镜像体积与安全性​

13 · 面试题卡片​

13.1 如何设计从提交到生产的可重复交付流水线​

出现公司:Shopee

题型:综合题

考察重点

  • 理解不可变镜像 digest、多阶段构建和构建输入。
  • 理解同产物晋升、签名、SBOM 与审计。
  • 理解readiness、排空、数据兼容和回滚边界。

相关内容:镜像与 digest至流水线故障演练。

参考回答

流水线构建一次镜像,再晋升经过验证的同一 digest。

CI 固定提交与工具链,完成测试和镜像检查。产物附带 SBOM、构建来源与签名。CD 注入环境配置,并校验来源策略。

发布需验证就绪、信号处理和连接排空。数据变更保持兼容,镜像回退单独验证。部署记录连接源码、digest、配置和运行实例。

13.2 构建私有依赖时怎样传密钥,轮换后缓存会失效吗?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:临时挂载、镜像层与缓存输入。

相关内容:构建缓存与凭据。

参考回答

使用 BuildKit 的 --secret 与 secret mount 传入凭据。

构建过程避免把内容写进产物或日志。密钥内容变化本身不会触发缓存失效。需要重新执行时,使用非敏感缓存版本参数。

13.3 容器收到 SIGTERM 后,Java 应用为何仍被强制结束?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:PID 1、信号转发与排空时限。

相关内容:容器终止信号。

参考回答

应检查 Java 是否收到信号,以及排空是否超时。

shell 形式入口会增加中间进程。exec 形式 ENTRYPOINT 可让 Java 直接接收信号。关闭钩子还需在宽限期内完成工作,否则平台会强制结束。

14. 参考资料​