Docker镜像由只读层堆叠构成,每层对应Dockerfile指令,通过OverlayFS等联合文件系统实现分层读写分离;lowerdir为只读层,upperdir为容器读写层,workdir为工作目录。

Linux中Docker镜像的分层与UnionFS(实际为OverlayFS等联合文件系统)是理解镜像构建、存储优化和运行时行为的关键。Docker本身不直接使用传统UnionFS,而是依赖宿主机内核支持的OverlayFS(主流)、aufs(旧版)、btrfs等联合挂载机制来实现镜像分层读写分离。
理解Docker镜像的分层结构
Docker镜像由一系列只读层(layers)堆叠构成,每层对应Dockerfile中的一条指令(如RUN、COPY、ADD),最底层是基础操作系统(如debian:slim的rootfs),顶层为镜像元数据(image config)。所有层按顺序叠加,形成统一的文件系统视图。
关键点:
- 层是内容寻址的:每层有唯一SHA256摘要(如sha256:abc123...),相同内容层在不同镜像间自动复用
- 镜像ID ≠ 最上层ID:镜像ID是其配置文件(config.json)的哈希,而非顶层文件系统层
-
docker history
可查看各层大小、创建命令、时间戳及是否为空( 表示中间层未被单独标记)
查看底层联合文件系统挂载细节
Docker守护进程启动时会将镜像层和容器读写层通过联合挂载方式组合成容器根文件系统。要观察真实挂载结构,需进入容器命名空间或检查宿主机挂载点:
- 运行容器后,执行:findmnt -t overlay 或 mount | grep overlay,可看到类似:
overlay on /var/lib/docker/overlay2/xxx-merged type overlay (rw,relatime,lowerdir=...,upperdir=...,workdir=...) - 其中:
lowerdir:多个只读层路径(用::分隔),从底到顶排列
upperdir:容器专属读写层(即容器修改都落在此目录)
workdir:OverlayFS内部工作目录(必须存在且空) - 各层物理路径位于/var/lib/docker/overlay2/下,以l/(layer ID映射)和l/xxx→diff/xxx软链关联
分析单个镜像层内容与差异
想确认某层具体修改了哪些文件,可解压镜像层tar包或对比相邻层:
- 用docker save
| tar -t 列出所有层tar路径(如a3f.../layer.tar) - 提取某层:mkdir layer && tar -xf layer.tar -C layer,观察新增/覆盖文件
- 更高效方式:用开源工具dive(github.com/wagoodman/dive)交互式浏览每层文件树、大小占比、冗余文件,并高亮变化
- 若需脚本化分析,可结合docker image inspect
获取RootFS.Layers数组,再用skopeo copy或umoci unpack 解包OCI格式层
验证联合挂载的读写行为
在容器中操作文件,可直观验证OverlayFS特性:
- 在容器内touch /tmp/a.txt → 文件出现在upperdir中
- 修改一个基础镜像带的文件(如/etc/hosts)→ OverlayFS会执行“copy-up”,将原文件从lowerdir复制到upperdir再修改
- 删除一个只读层中的文件(如rm /bin/bash)→ OverlayFS生成一个特殊“whiteout”文件(如.wh.bin)在upperdir中,屏蔽下层同名项


















