Docker构建缓存机制的核心是内容哈希精准锁定每层唯一状态。它基于联合文件系统和内容寻址,以指令文本、父层哈希、文件内容哈希三者共同决定层标识,全等才复用,微小偏差即强制重建。
docker 构建缓存机制的核心,不是“记住上次怎么做的”,而是“用内容哈希精确锁定每一层的唯一状态”。它不依赖时间戳、版本号或人工标记,而是基于联合文件系统(如 overlay2)和内容寻址(content-addressable)的底层设计,逐层验证输入是否完全一致。
镜像层即缓存单元
Dockerfile 中每条有效指令(FROM、COPY、RUN、ENV 等)都会生成一个只读镜像层。这个层本身就是一个缓存项,其标识由三部分共同决定:
- 该指令的完整文本(含空格、换行、注释——改一行注释也会失效)
- 其所有父层的哈希值(自上而下链式依赖)
- 若涉及文件操作(如 COPY ./src /app),则包含构建上下文中对应文件的完整内容哈希(递归计算)
缓存命中不是“相似就用”,而是“全等才复用”
执行 docker build 时,Docker 并非简单比对指令字符串,而是构造一个“构建上下文快照”:
- 对 COPY 和 ADD,会扫描 .dockerignore 后实际参与的每个文件,并计算其 SHA256
- 对 RUN,不仅校验命令字符串,还隐式包含前一层的文件系统状态(即父层哈希)和构建时环境变量(ARG/ENV)
- 一旦某层未命中,Docker 不会“跳过并继续比对下一层”,而是直接中断缓存链,从该层开始全部重建
基础镜像更新为何不自动刷新缓存?
FROM nginx:1.25 这类标签是“可变引用”,其实际镜像 ID 可能随时间变化。但 Docker 缓存只认当前本地已拉取的镜像 ID —— 即使远程仓库中 nginx:1.25 已更新补丁,本地缓存仍指向旧层。
- 不加 --pull,Docker 默认不检查远程基础镜像变更
- 使用 latest 标签会让缓存行为不可预测,极易导致安全漏洞残留
- 真正可控的做法是固定 digest:FROM nginx@sha256:abc123...
BuildKit 带来的根本性升级
传统构建引擎按顺序逐层比对;BuildKit 则将整个 Dockerfile 编译为有向无环图(DAG),支持:
- 细粒度内容块缓存:RUN 指令内部可拆解为多个子操作,仅变更部分重跑
- --mount=type=cache:在构建过程中挂载可跨层复用的临时目录(如 node_modules、~/.m2),绕过 COPY 层限制
- 并发执行无依赖层:例如多个独立的 COPY 操作可并行进行,提升 CPU 利用率
本质上,Docker 缓存不是优化技巧,而是存储系统与构建逻辑深度耦合的产物。理解它,关键在于放弃“缓存是可选加速”的认知,转而视其为构建过程的确定性契约——任何输入微小偏差,都会被哈希机制精准捕获并强制重建。


















