目录
[1. 核心分层架构](#1. 核心分层架构)
[(2)写时复制(Copy-On-Write, COW)](#(2)写时复制(Copy-On-Write, COW))
[二、Docker中的AUFS 与OverlayFS /Overlay2](#二、Docker中的AUFS 与OverlayFS /Overlay2)
[1. AUFS(Advanced UnionFS):Docker 早期核心存储驱动](#1. AUFS(Advanced UnionFS):Docker 早期核心存储驱动)
[(2)核心技术机制:Whiteout 与 Opaque](#(2)核心技术机制:Whiteout 与 Opaque)
[2. OverlayFS/Overlay2:Docker 当前默认存储驱动](#2. OverlayFS/Overlay2:Docker 当前默认存储驱动)
[(1)核心架构:四目录极简模型(对比 AUFS)](#(1)核心架构:四目录极简模型(对比 AUFS))
[(2)Overlay2 对 OverlayFS 的核心优化](#(2)Overlay2 对 OverlayFS 的核心优化)
[(3)Docker 中 Overlay2 的实际应用](#(3)Docker 中 Overlay2 的实际应用)
[3.AUFS 与 Overlay2 核心差异汇总](#3.AUFS 与 Overlay2 核心差异汇总)
[三、UnionFS 的跨领域应用场景](#三、UnionFS 的跨领域应用场景)
在 Docker 容器技术体系中,镜像分层是其核心特性之一,而支撑这一特性实现的底层技术,正是UnionFS(联合文件系统)。从早期的 AUFS 到如今 Docker 默认的 Overlay2,UnionFS 通过 "联合挂载" 的思想,解决了容器镜像存储、数据隔离与高效复用的核心难题。
一、UnionFS:容器分层存储的核心思想
UnionFS 并非某一个具体的文件系统,而是一种文件系统抽象理念,核心通过"联合挂载(Union Mount)"技术实现:将多个物理 / 逻辑独立的 "层(Layer)" 按指定规则叠加,对外呈现为一个统一、虚拟的文件系统视图。
1. 核心分层架构
UnionFS 将存储层分为两类,各司其职,实现资源共享与数据隔离的统一:
1.底层分支(只读层,Image Layers):对应 Docker 镜像的底层层(如基础镜像层、依赖安装层);
2.上层分支(可写层,Container Layer):对应 Docker 容器的运行时层(容器内修改仅作用于此层)。
3.虚拟挂载点:用户 / 进程仅能看到合并后的统一目录,无法直接感知底层分层,简化了使用复杂度。
核心价值是用分层思想实现资源共享与数据隔离,既提升存储效率,又保障容器环境的独立性。
2. 四大核心特性
(1)分层合并与视图统一
将多个只读层(镜像层)与一个可写层(容器层)合并,对外呈现为单一文件系统。
创建layer1(含 file1、file2)、layer2(含 file1、file3)两个只读层,通过mount -t aufs -o br:upperlayer:layer1:layer2 none mountedfs挂载后,mountedfs目录中能看到 file1(来自 layer1)、file2(来自 layer1)、file3(来自 layer2),即 "合并后视图"。
(2)写时复制(Copy-On-Write, COW)
对合并视图中的文件进行修改、创建、删除时,不会直接修改底层只读层,仅将操作作用于上层可写层,避免底层数据污染。
示例 1(创建文件):在 AUFS 的mountedfs目录创建 file4,实际文件会写入upperlayer(可写层),layer1/layer2(只读层)无变化;
示例 2(删除文件):删除mountedfs中的 file1 时,AUFS 会在upperlayer创建/.wh.file1(whiteout 文件)标记 "隐藏底层 file1",而非删除layer1中的原始 file1;若后续重新创建 file1,/.wh.file1会被删除,新 file1 直接写入upperlayer。
(3)层优先级覆盖
当不同层存在同名文件 / 目录时,左侧层(优先级更高)的内容会覆盖右侧层,确保上层修改能 "屏蔽" 底层静态数据。
示例:AUFS 挂载时指定分支顺序upperlayer:layer1:layer2,layer1和layer2均有 file1,最终mountedfs中显示layer1的 file1 内容;若调整顺序为upperlayer:layer2:layer1,则会显示layer2的 file1 内容。
(4)底层隔离与资源节省
各层独立存储,相同基础层可被多个容器共享(如多个 Docker 容器共用同一个 Nginx 基础镜像层),无需重复存储,大幅节省磁盘空间。
Docker 镜像的 "分层构建" 机制(每条 Dockerfile 指令生成一个只读层)正是基于 UnionFS 的共享特性,例如多个容器基于python:3.12-slim镜像构建时,仅需存储一份基础镜像层,容器运行时仅新增一个可写层。
二、Docker中 的 AUFS 与OverlayFS /Overlay2
UnionFS 有多种落地实现(如 AUFS、OverlayFS、UnionFS-FUSE 等),其中 Docker 生态中最具代表性的是早期使用的 AUFS,以及当前默认的 OverlayFS/Overlay2。二者均遵循 UnionFS 核心理念,但在内核支持、性能表现、功能扩展性上存在显著差异。
1. AUFS(Advanced UnionFS):Docker 早期核心存储驱动
AUFS 是 UnionFS 技术规范的增强实现,也是 Docker 初期在 Debian、Ubuntu 等系统上的默认存储驱动,完美支撑了早期容器分层构建、多容器共享镜像的核心需求。
(1)核心工作逻辑
AUFS 以"分支(Branches)"为核心分层单位,将所有存储节点划分为两类分支,分工明确、互不干扰:
只读分支(Read-Only Branches):对应 Docker 镜像的所有底层分层,包括基础操作系统层、应用依赖安装层等,一旦生成便不可修改,多个容器可共用同一组只读分支,大幅节省存储资源;
可写分支(Read-Write Branch):专门对应 Docker 容器的运行时分层,容器启动后,所有文件新增、修改、删除操作,均仅在该分支内执行,不会对只读分支的原始数据造成任何影响。
bash
# 1. 创建分层目录(2个只读层+1个可写层+1个挂载点)
mkdir aufs-test && cd aufs-test
mkdir layer1 layer2 upperlayer mountedfs
# 2. 向只读层写入测试文件(layer1和layer2有同名file1)
echo "content for file1 in layer1" > layer1/file1
echo "content for file1 in layer2" > layer2/file1
echo "content for file2 in layer1" > layer1/file2
echo "content for file3 in layer2" > layer2/file3
# 3. 挂载AUFS:指定分支顺序(upperlayer可写层在前,layer1/layer2只读层在后)
mount -t aufs -o br:upperlayer:layer1:layer2 none mountedfs
# 4. 验证合并结果:file1来自layer1(优先级高),file2来自layer1,file3来自layer2
cd mountedfs && cat file1 # 输出"content for file1 in layer1"
(2)核心技术机制:Whiteout 与 Opaque
为了实现"不修改只读层却能隐藏底层文件/目录"的效果,AUFS 设计了两种特殊标记文件,这也是其核心技术亮点:
Whiteout(文件隐藏标记):当删除合并视图中的某个文件时,AUFS 不会删除只读分支中的原始文件,而是在可写分支中创建一个名为 .wh.文件名 的空文件,以此标记"该文件在合并视图中隐藏",底层原始文件仍完整保留;
Opaque(目录隐藏标记):若删除合并视图中的某个目录,AUFS 会在可写分支中创建 .wh..wh.opaque 文件,标记"该目录及旗下所有子内容在合并视图中隐藏",避免底层目录内容意外暴露。
(3)逐步被淘汰的核心原因
随着 Docker 普及和容器场景复杂化,AUFS 的局限性逐渐凸显,最终被 Overlay2 取代,核心短板有三点:
内核兼容性差:AUFS 并非 Linux 内核原生支持的文件系统,需要额外安装内核补丁才能使用,仅适配 Ubuntu、Debian 等少数发行版,CentOS、RHEL 等主流服务器系统无原生支持;
性能损耗明显:作为用户态文件系统,AUFS 的文件查找、读写操作需要经过用户态与内核态的多次切换,当镜像分层超过 10 层时,延迟会显著增加;
功能扩展性弱:最多仅支持 127 个分层,无法适配复杂镜像的分层需求,且不支持目录重命名等基础操作,灵活性不足。
2. OverlayFS/Overlay2:Docker 当前默认存储驱动
OverlayFS 是 Linux 内核原生支持的 UnionFS 实现(自 Linux 3.18 版本引入),专门解决了 AUFS 兼容性差、性能弱的问题;Overlay2 是其改进版本,自 Docker 17.06 版本起成为默认存储驱动,也是目前生产环境中最推荐的选择。
(1)核心架构:四目录极简模型(对比 AUFS)
相比 AUFS 复杂的分支管理,OverlayFS 的分层模型更简洁,核心仅包含四类目录,与 AUFS 的对应关系清晰,便于理解和维护:
|--------------|-----------------------------------------------------|----------------------------------------|
| OverlayFS 目录 | 核心作用(对应 Docker 场景) | 与 AUFS 的对应关系 |
| lowerdir | 存放所有只读层的集合(即 Docker 镜像的全部底层分层),可包含多个只读目录,用冒号分隔 | 对应 AUFS 的所有只读分支(ro-layer1、ro-layer2 等) |
| upperdir | 专门存放容器运行时的所有修改数据,即 Docker 容器的可写层,仅对当前容器生效 | 对应 AUFS 的可写分支(rw-layer) |
| workdir | 临时工作目录,用于 OverlayFS 内部处理文件重命名、删除等操作,必须为空目录,用户无需手动操作 | AUFS 无对应独立目录,同类操作依赖可写分支完成 |
| merged | 分层合并后的虚拟视图,也是 Docker 容器内部看到的根文件系统,屏蔽所有底层分层细节 | 对应 AUFS 的挂载点(mount-point) |
bash
# 1. 创建分层目录(2个只读层+1个可写层+1个工作目录+1个挂载点)
mkdir overlay-test && cd overlay-test
mkdir layer1 layer2 upperlayer workdir mountedfs
# 2. 写入测试文件(同AUFS实验,layer1和layer2有同名file1)
echo "content for file1 in layer1" > layer1/file1
echo "content for file1 in layer2" > layer2/file1
echo "content for file2 in layer1" > layer1/file2
echo "content for file3 in layer2" > layer2/file3
# 3. 挂载OverlayFS:指定lowerdir(只读层,优先级左高右低)、upperdir(可写层)、workdir(临时目录)
mount -t overlay -o lowerdir=layer1:layer2,upperdir=upperlayer,workdir=workdir overlay mountedfs
# 4. 验证合并结果:与AUFS一致,file1来自layer1,且修改仅作用于upperdir
cd mountedfs && echo "new file4" > file4 && ls ../upperlayer # file4存在于upperdir
(2)Overlay2 对 OverlayFS 的核心优化
原生 OverlayFS 存在明显短板------仅支持"1 个可写层 + 1 个只读层",无法满足 Docker 镜像多分层(通常超过 10 层)的实际需求。Overlay2 作为改进版,重点解决了这一问题,同时优化了性能:
分层数量突破:通过"链式分层"技术,将多个只读层组织成链式结构,每层记录前一层的引用关系,最终实现 128 个只读层的合并,完全适配复杂 Docker 镜像;
性能大幅提升:引入"原生 Overlay Diff"机制,减少文件元数据的重复计算和存储,在多分层场景下,读写延迟比 AUFS 降低 30%~50%,接近原生文件系统性能;
兼容性全面升级:Linux 4.0 及以上内核默认支持 Overlay2,无需安装任何补丁,可完美适配 Ubuntu、CentOS、RHEL、统信 UOS 等所有主流 Linux 发行版,部署成本极低。
(3)Docker 中 Overlay2 的实际应用
作为 Docker 当前默认存储驱动,Overlay2 已深度融入 Docker 容器的运行机制,核心应用细节如下:
验证默认驱动:通过简单命令即可查看 Docker 当前使用的存储驱动,确认是否为 Overlay2:
bash
docker info | grep "Storage Driver" -A5
# 输出结果(文档示例):
# Storage Driver: overlay2
# Backing Filesystem: extfs
# Supports d_type: true
# Using metacopy: false
# Native Overlay Diff: true
# userxattr: false
存储路径规范:Docker 容器的 Overlay2 所有分层数据,均存储在 /var/lib/docker/overlay2/ 目录下,每个容器对应一个以"容器 ID"命名的子目录;
目录结构对应:每个容器子目录内,包含 diff(对应可写层 upperdir)、work(对应临时工作目录 workdir)、merged(对应合并视图 merged)三个核心目录;
层关联机制:容器子目录下的 mount-id 文件,记录了该容器与 /var/lib/docker/overlay2/ 中只读分层目录的关联关系,确保容器启动时能精准找到对应的所有只读层,完成分层合并。
3.AUFS 与 Overlay2 核心差异汇总
|-------------|---------------------------|--------------------------------|
| 对比维度 | AUFS | Overlay2 |
| 内核支持情况 | 非原生,需额外安装补丁,仅适配少数发行版 | 原生支持(Linux 4.0+),适配所有主流发行版 |
| 最大支持分层数 | 127 层,无法适配复杂镜像 | 128 层,链式分层适配多分层场景 |
| 性能表现 | 用户态实现,多分层场景延迟高、损耗大 | 内核态实现,多分层场景性能优异,延迟低 |
| 临时目录需求 | 无独立临时目录,依赖可写分支处理内部操作 | 必须指定空的 workdir 临时目录,操作更高效 |
| 写时复制机制 | 依赖 Whiteout/Opaque 标记文件实现 | 直接在 upperdir 写入/覆盖,删除时标记隐藏,更简洁 |
| Docker 支持状态 | deprecated(逐步淘汰),仅旧版环境兼容 | 默认推荐,生产环境首选,持续迭代优化 |
三、UnionFS 的跨领域应用场景
容器镜像分层:Docker 镜像的分层构建、增量传输核心,基础镜像层共享,仅差异层存储,大幅节省空间;
容器运行时:K8s、Docker 容器的根文件系统基于 UnionFS,实现环境隔离+轻量运行;
嵌入式系统:路由器、智能设备固件采用"只读固件层+可写配置层",既防篡改,又支持用户自定义配置;
Live CD/USB:系统镜像只读加载,可写层存放用户操作,重启后恢复初始状态,保障系统安全。
简言之,没有 UnionFS,容器镜像的轻量级与可移植性便无从谈起 ------ 它正是容器分层存储思想在文件系统层面的核心落地。