Overlay2是Docker镜像分层共享的物理基础,通过lowerdir(多个只读镜像层)、upperdir(容器可写层)和workdir(内部辅助目录)联合挂载为merged统一视图,并依托diff_id与cache-id哈希映射实现跨镜像层复用。
Overlay2 是 Docker 镜像分层共享的物理基础,它把“镜像由多层组成”这个抽象概念,落地为 Linux 内核支持的文件系统挂载行为。理解它,就等于看清了镜像为什么能复用、为什么拉取快、为什么构建可缓存。
每个运行中的容器背后,都对应一个 Overlay2 挂载点,由三个关键目录协同工作:
/var/lib/docker/overlay2/<hash>/diff
三者合并后,通过 merged 目录对外提供统一视图——这就是容器看到的根文件系统。
Overlay2 不靠路径名识别层,而是依赖内容哈希(diff_id)和缓存 ID(cache-id)实现跨镜像共享:
RUN apt-get install nginx)生成完全一致的文件变更集 → 计算出相同 diff_id
diff_id 映射为唯一的 cache-id,并存入 /var/lib/docker/image/overlay2/layerdb/sha256/<cache-id>
cache-id 对应的 /var/lib/docker/overlay2/<hash> 目录,无论多少个镜像引用它,都复用同一份物理数据例如两个不同应用镜像都基于 alpine:3.18,它们的 base layer 在 lowerdir 中指向同一个 /var/lib/docker/overlay2/abc123.../diff,不重复存储。
分层不是静态快照,而是随生命周期动态参与:
RUN/COPY 指令执行后,Docker 将临时容器的 upperdir 打包为新层,生成 diff_id 并存入 layerdb;若该层已存在,则跳过执行,直接复用lowerdir)+ 新建空 upperdir + workdir 一起挂载到 merged;文件读取从上往下查,写入触发 Copy-on-Write —— 修改文件先复制到 upperdir 再编辑这意味着:镜像层永远只读、不可变;容器层仅记录增量;底层未改动,上层就不会冗余复制。
不需要深入代码,几条命令就能印证设计:
docker image inspect nginx | jq '.[0].RootFS.Layers' → 输出一串 sha256:xxx,即各层 diff_id
cat /var/lib/docker/image/overlay2/layerdb/sha256/<diff_id>/cache-id → 得到 cache-id,再进 /var/lib/docker/overlay2/<cache-id>/diff 看真实文件find /var/lib/docker/overlay2 -name "diff" -path "*/<cache-id>/*" | wc -l → 若返回 1,说明该层只被一个镜像引用;若多个镜像共用,此 cache-id 会被多个镜像的元数据指向这种基于内容哈希与内核挂载的组合,让分层不只是逻辑划分,而是真正可验证、可复用、可隔离的存储事实。