首页/开发/CI/CD 与发布速查/Dockerfile 层顺序与缓存命中
构建与制品管理58 条

Dockerfile 层顺序与缓存命中

按变化频率排序:低频的依赖声明在前、易变的源码在后,使代码改动不触发依赖重装,构建缓存持续命中。

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

层顺序与缓存是什么

Dockerfile 的每条指令形成一个缓存单元:某层失效后,其后续所有层都要重新构建。把变化频率低的指令放前面、易变的源码放后面,是让依赖安装层持续复用、缩短构建时间的核心手法。观察方式:看构建日志里的缓存标记与各步耗时分布,命中率高说明顺序与复制范围划得对。

基本信息

适用平台Docker 与 BuildKit 等兼容构建器
原则变化越频繁的指令越靠后
典型模式先复制锁文件 → 安装依赖 → 再复制源码 → 构建
观察构建日志里的缓存标记与耗时分布
常见失误先复制源码再装依赖,任一源码文件改动都会让依赖层重跑
排查方法借构建输出逐层确认缓存命中与重建原因

典型使用场景

  • Node 项目:依赖清单先复制,源码后复制,改动代码不触发重装
  • 多语言项目:各包管理器清单先行(go.mod、pom.xml、Cargo.toml)
  • CI 提速:合并请求频繁构建的场景收益最直接
  • 镜像演进:系统包安装放最前,业务迭代不影响它们
  • 排查变慢:对比各层耗时,找到反复失效的源头
  • 私有依赖场景:在镜像内配置包管理器缓存与代理,避免每次都从上游全量拉取

Node 示例

Node 示例
FROM node:20-slim
WORKDIR /app
COPY package.json package-lock.json ./  # 只复制清单,内容长期稳定
RUN npm ci  # 依赖层:代码改动时正常命中缓存
COPY . .  # 源码最后进入,变化频率最高
RUN npm run build

顺序原则

位置放什么原因
最前基础镜像与系统包几乎不变,永远命中
中间依赖清单与安装随版本更新而变
最后业务源码与构建每次提交都在变
RUN 指令合并要平衡:过度合并会让「某一步变化全部重跑」,按变化频率分界。
忽略文件也是缓存的一部分:测试数据与日志进构建上下文会意外触发失效,维护好忽略清单。

易错点

  • 先复制整个目录再装依赖:改一行代码就重装全部依赖,构建时长成倍
  • 锁文件与源码分开复制后忘记更新:依赖层用旧锁,实际安装与仓库不一致
  • 构建参数位置随意:参数变化会让其后所有层失效,把参数声明挪到无关步骤之后
  • 只在本地优化顺序:CI 的构建上下文与本地不同,缓存效果要在流水线上复测

数据来源与参考

  • Docker Docs《Best practices for writing Dockerfiles》
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌