UnionFS 是 Docker 早期分层存储驱动,通过多只读层叠加加一层可写层实现镜像分层与容器读写分离,但因内核支持差、性能低、whiteout 复杂等缺陷,已被更稳定高效的 overlay2 取代。

UnionFS 是 Docker 早期使用的分层存储驱动之一,它通过将多个目录(称为“分支”)叠加成一个统一的文件系统视图,实现镜像分层和容器读写分离。虽然现代 Docker 默认已切换到 overlay2(更稳定、性能更好),但理解 UnionFS 的原理对掌握 Docker 存储机制仍有帮助。
UnionFS 的核心思想:多层只读 + 一层可写
UnionFS 将文件系统分为若干层,通常包括:
- 底层多个 只读层(Read-Only Layers):对应镜像的每一层(如基础 OS、运行时、应用依赖等),按构建顺序堆叠;
- 顶层一个 可写层(Upper Layer / Read-Write Layer):容器启动后挂载,所有新增、修改、删除操作都发生在此层;
- 一个 合并视图(Merged View):用户看到的统一目录结构,由 UnionFS 驱动动态合成。
例如,当容器内读取 /bin/bash,UnionFS 从上往下查找,优先返回可写层中的副本(如有);若无,则返回最靠近顶部的只读层中匹配的文件。
Docker 中 UnionFS 的实际挂载方式
Docker 启动容器时,会为该容器创建独立的可写层,并将其与镜像各层一起传给 UnionFS 驱动(如 aufs 或 unionfs-fuse)进行挂载。典型挂载命令逻辑类似:
mount -t aufs -o br=/var/lib/docker/aufs/diff/[container-id]=rw:/var/lib/docker/aufs/layers/[layer-id1]=ro:... none /var/lib/docker/aufs/mnt/[container-id]
其中:
-
br=指定分支列表,=rw表示可写层,=ro表示只读层; -
/mnt/[container-id]是最终供容器 rootfs 使用的合并挂载点; - 所有只读层通过
layers/下的元数据文件记录依赖关系,确保复用和共享。
UnionFS 在 Docker 中的局限性与替代原因
尽管设计简洁,UnionFS(尤其是 AUFS)在生产环境暴露了若干问题:
- 内核支持不稳定:AUFS 未被主线 Linux 内核接纳,需打补丁或使用第三方模块;
- 并发性能瓶颈:多容器同时写入大量小文件时,目录遍历和 whiteout 处理开销显著;
-
whiteout 机制复杂:删除文件需创建特殊隐藏文件(
.wh.)标记,易出错且难以调试; - 缺乏原子提交与校验:镜像层构建过程不保证一致性,损坏后难以定位。
因此 Docker 自 1.13+ 默认启用 overlay2,它基于内核原生 overlayfs 支持,简化 whiteout 实现(使用 trusted.xattr)、支持 128 层以上、具备更好的并发与稳定性。
如何查看当前 Docker 使用的存储驱动
运行以下命令即可确认:
docker info | grep "Storage Driver"
输出如 Storage Driver: overlay2 表示已切换;若仍显示 aufs,说明运行在较老内核(如 Ubuntu 14.04)且未手动配置。可通过修改 /etc/docker/daemon.json 强制指定(需重启 dockerd):
{ "storage-driver": "overlay2" }










