# 存储引擎
Docker 存储引擎是 Docker 容器管理文件系统的核心组件,负责镜像层与容器层的组织、读写操作及资源隔离。其核心在于通过联合文件系统(UnionFS)和写时复制(Copy-on-Write, CoW)机制实现高效存储管理。
## 分层存储与联合挂载
Docker镜像由多个只读层(Layer)叠加而成,容器运行时会在镜像层之上创建可写层。所有层通过 UnionFS 联合挂载到同一视图,上层文件覆盖下层同名文件,但底层数据保持不变。
UnionFS(联合文件系统)是一种分层、轻量级且高性能的文件系统技术,通过将多个目录(分支)联合挂载到同一目标目录,形成统一的文件系统视图。核心机制如下:
- **分层存储**:UnionFS 通过分层结构管理文件,每个层(分支)可以是只读或可写。不同层中相同路径的文件会被上层覆盖,但底层内容保持不变。
- **只读层和可写层**:只读层通常为基础镜像或依赖文件,不可修改;可写层:容器运行时新增的层,所有修改均在此层记录。
## 写时复制(CoW)机制
当容器需要修改文件时,存储引擎将文件从底层只读层复制到可写层进行修改,而非直接修改原始数据。这种机制减少冗余存储,允许多容器共享同一镜像层,显著降低磁盘占用。
## 工作原理
- **联合挂载(Unio Mount)**:将多个物理目录(如目录A和B)挂载到同一虚拟目录(如目录C),合并后的视图包含所有分支目录的内容。若存在同名文件,优先显示上层文件。
- **访问优先级**:用户访问文件时,UnionFS按层从上至下搜索,返回第一个匹配的文件。例如,可写层优先级高于只读层。
- **数据隔离与共享**:不同容器共享同一基础镜像层,但各自的可写层独立,实现资源复用与运行时隔离。
# 主流存储引擎
Docker支持多种存储驱动,不同驱动在性能、稳定性、适用场景上存在差异:
| 存储驱动 | 特点 | 优势 | 局限性 | 适用场景 |
|---------|------|------|--------|----------|
| OverlayFS | • Linux内核原生支持(≥3.18)
• 使用overlay2驱动
• 仅需一个只读层和一个可写层
• 结构简单且性能优异 | • 启动速度快
• 适合生产环境
• 支持高效的文件系统层叠
• 节省存储空间 | • 层数限制(通常≤127层)
• 频繁小文件写入可能增加I/O开销 | • 通用容器环境
• 需要高性能的生产系统
• 对存储空间敏感的场景 |
| AUFS | • 通过多层联合挂载实现CoW
• 稳定性较好
• 未集成到内核,需额外安装 | • 内存利用率高
• 适合旧版Linux系统 | • 高并发写入性能较差
• 逐渐被OverlayFS替代 | • 旧版Linux系统
• 对内存资源敏感的环境
• 低并发写入场景 |
| Device Mapper | • 基于块设备映射
• 使用"thin pool"技术
• 支持动态扩容 | • 支持精细的存储控制
• 适合块级存储需求
• 动态扩容能力强 | • 配置复杂
• 需预分配存储池
• 可能导致空间浪费 | • 数据库容器
• 需要精细存储控制的场景
• 大规模存储系统 |
| Btrfs/ZFS | • 支持高级功能(快照/去重/压缩)
• 文件系统级别的功能丰富 | • Btrfs写入密集型场景表现优异
• ZFS提供数据完整性校验
• 支持高效压缩 | • 对系统内核版本依赖性强
• 稳定性与兼容性需验证 | • 需要数据快照功能
• 写入密集型应用
• 对数据完整性要求高的场景 |
# Overlay2
## 工作原理
Docker 默认存储驱动。通过以下三个主要目录来管理文件系统:
- **`LowerDir`**:只读层,包含基础镜像的文件系统。可以有多个只读层,每层都是独立的。
- **`UpperDir`**:读写层,用于存储容器运行时的文件系统变更(即 diff 层)。
- **`MergedDir`**:联合挂载后的视图,容器看到的完整文件系统。它将 `LowerDir` 和 `UpperDir` 合并为一个统一的文件系统视图。
- **`WorkDir`**:是系统内部使用的临时目录,用于处理写时复制(CoW)和元数据操作。其内容在挂载时会被清空,且运行时不可见,一般不要动。
当启动一个容器时,Overlay2 会将镜像层(`LowerDir`)和容器层(`UpperDir`)联合挂载到 `MergedDir`,容器通过这个目录看到完整的文件系统。
## 实践案例1
通过 Overlay2 挂载目录,理解镜像层与容器层的交互逻辑。
```shell
# 1.目录结构 & 文件
mkdir -p /mnt/overlay2/{lower,upper,work,merged}
echo "基础文件内容" > /mnt/overlay2/lower/base.txt
echo "初始配置" > /mnt/overlay2/lower/config.yaml
# 2.挂载Overlay2
mount -t overlay overlay \
-o lowerdir=/mnt/overlay2/lower,upperdir=/mnt/overlay2/upper,workdir=/mnt/overlay2/work \
/mnt/overlay2/merged
# 3.模拟容器操作
echo "容器修改内容" > /mnt/overlay2/merged/base.txt
## CoW机制生效
[root@master01 ~]# cat /mnt/overlay2/upper/base.txt
容器修改内容
[root@master01 ~]# cat /mnt/overlay2/lower/base.txt
基础文件内容
## 文件名 #40b 是 OverlayFS 在处理文件操作时生成的临时标识符,用于跟踪操作状态
rm /mnt/overlay2/merged/config.yaml
# 卸载并清理
umount /mnt/overlay2/merged
rm -rf /mnt/overlay2/*
```
## 实践案例2
验证运行容器的存储结构,并能快速定位。
```shell
# LowerDir、MergedDir、UpperDir、WorkDir
[root@master01 ~]# docker inspect 379c14648fbb
[root@master01 ~]# docker exec -it 3eb8f9c95ab4 touch /root/1.txt
[root@master01 ~]# ls /var/lib/docker/overlay2/869a09f00704dbbb396d8be90d52b73870073c0a294deceac24a69afbe1a4310/diff/root/
1.txt
```
# 扩展阅读
存储引擎文档:
https://docs.docker.com/storage/storagedriver/select-storage-driver/
存储引擎血案:
https://www.cnblogs.com/youruncloud/p/5736718.html