人人都会AI编程

26.3 UnionFS 联合文件系统:镜像分层的底层原理

更新时间:2026-07-12

如果你使用过 Docker,一定对“镜像分层”有印象:一个镜像可以由多个只读层(layer)叠加而成,最上面再加一个可写层(容器层)。这种灵活构建和高效复用的能力,依赖的就是 UnionFS(联合文件系统) 技术。

什么是联合文件系统?

UnionFS 是一种可以将多个目录(或文件系统)叠加在一起,对外呈现为单一合并视图的机制。它在挂载时,允许指定多个分支(branch),这些分支可以具有不同的读写权限。最终看起来,所有文件都位于同一个目录树中,但实际上它们可能分散在不同的物理层上。

对于 Docker 来说,这些分支就是镜像的层:

  • 多个只读层对应基础镜像和后续构建步骤添加的层(如安装软件、复制文件等);
  • 一个可写层对应启动容器时新创建的容器层,用于保存运行时产生的修改。

写时复制(Copy-on-Write)的精髓

当你在容器中修改一个文件时,文件系统并不会直接修改只读层中的原始文件,而是触发 写时复制(Copy-on-Write):

  1. 系统发现该文件位于下层的只读层中;
  2. 将该文件复制到顶部的可写层;
  3. 修改操作在可写层的这份副本上完成。

如果不再需要该修改,删除容器后,只需丢弃这个可写层即可,底层只读层完全不受影响。这种机制带来了两大好处:

  • 高效共享:同一台宿主机上运行 100 个基于相同基础镜像(比如 ubuntu:22.04)的容器时,基础镜像的只读层在内存和磁盘上仅需保存一份,可写层各自独立,极大节省了存储空间和内存。
  • 快速启动:启动新容器不需要复制整个根文件系统,只需新建一个薄薄的可写层并与已有层联合挂载。这也是容器可以“秒级启动”的关键。

Docker 使用的具体实现

Docker 并不绑定单一的联合文件系统,而是支持多种后端驱动,常见的有:

  • OverlayFS(现代 Linux 推荐):已集成在主流 Linux 内核中,性能好、设计简洁。默认分两层联合:lowerdir(只读层)和 upperdir(可写层),通过一个 merged 目录呈现合并视图。
  • AUFS(早期 Docker 使用):曾是 Docker 默认驱动,但一直未被主线内核合并,逐渐被 OverlayFS 取代。
  • devicemapperbtrfs 等:通过块级别快照来模拟分层,现在较少直接推荐使用。

以 OverlayFS 为例,可以直观地感受联合挂载:

mkdir lower upper merged work
echo "来自只读层" > lower/file.txt
sudo mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged
cat merged/file.txt          # 输出 “来自只读层”
echo "修改内容" >> merged/file.txt
cat upper/file.txt           # 文件已被复制到可写层并修改

当查看 merged 目录时,文件系统自动合并了两个目录的内容;修改时,行为完全符合写时复制规则。

镜像构建中的层复用

每条 Dockerfile 指令(RUNCOPYADD)都会创建一个新的只读层,镜像就是这些层的叠加。当再次构建时,如果某一层及其之前的所有层都没有变化,Docker 会直接使用缓存,只重建发生变化的层和之后的层。这极大加快了代码更新和持续集成的速度。

实用意义总结

  • 存储节约:多个镜像和容器共享相同的底层只读层,物理磁盘上只占用一份空间。
  • 启动加速:容器不需要复制系统镜像,联合挂载加上写时复制实现了几乎即时的环境就绪。
  • 构建效率:分层缓存让重复构建变得飞快,只有发生变化的步骤才需要重新执行。
  • 环境一致性:基础镜像作为只读层被所有容器共享,用户无法直接修改,保证了环境基准的统一。

理解 UnionFS 与写时复制,你就掌握了 Docker 镜像体积小、启动快、缓存聪明背后的技术基石。这也是容器技术轻量化特征的根本来源。