UnionFS通过“只读层叠加+可写层独立”实现镜像分层复用:镜像各层为只读差异目录,容器启动时挂载为ro层堆叠+专属rw层,读写由Copy-on-Write机制统一处理。

UnionFS 的分层机制是 Docker 镜像能高效复用、快速启动的核心。理解镜像在 UnionFS 中的挂载过程,关键在于看清“只读层叠加 + 可写层独立”这一结构如何被动态组合成容器可见的文件系统。
镜像层本质是只读的目录快照
每个镜像层对应一个独立目录(如 /var/lib/docker/aufs/layers/xxx),里面保存的是该构建步骤产生的文件差异。比如 RUN apt install nginx 生成的一层,只包含新增的二进制、配置和依赖文件,不包含整个操作系统。这些层按构建顺序堆叠,从下到上形成依赖链,但全部标记为只读(=ro)。
容器启动时挂载:只读层 + 独立可写层
执行 docker run 时,Docker 会为该容器创建一个专属的可写目录(如 /var/lib/docker/aufs/diff/container-id),并调用 UnionFS 驱动(如 aufs)发起一次挂载:
- 命令逻辑类似:mount -t aufs -o br=/diff/container-id=rw:/layers/layer1=ro:/layers/layer2=ro ... none /mnt/container-id
- br= 参数明确列出所有分支,顺序决定查找优先级:最左边(rw 层)最高,逐层向下回退
- 最终挂载点(如 /mnt/container-id)就是容器看到的 / 根文件系统
文件读写行为由 UnionFS 动态合成
用户在容器内操作文件时,并不直接访问某一层,而是通过 UnionFS 视图统一处理:
- 读取:从可写层开始找;若不存在,依次往下查,返回第一个匹配项
- 修改已有文件:触发写时复制(Copy-on-Write),先将原始文件从只读层拷贝到可写层,再编辑
- 删除文件:在可写层创建 whiteout 文件(如 .wh.filename),遮蔽下层同名文件,实现逻辑删除
为什么现在默认不用 UnionFS 了
虽然原理清晰,但 AUFS 等 UnionFS 实现存在明显短板:
- whiteout 机制靠普通文件模拟,易出错且难以调试
- 未进入 Linux 主线内核,需额外维护模块,稳定性受限
- 大量小文件并发写入时性能下降明显
- overlay2 改用内核原生 overlayfs,用扩展属性(xattr)管理 whiteout,支持更多层级和更强一致性


















