文章目录
- 容器镜像与 Overlay2 存储
-
- 一、容器镜像概述
-
- 1. Docker 镜像
- 2. 联合文件系统(UnionFS)
- 二、Docker Overlay2 存储驱动
-
- 1. 存储驱动说明
- 2. 核心概念
- 3. Overlay2 分层结构
- 4. 元数据(Metadata)
- 5. 为什么下载慢、删除快?
- 6. OverlayFS 与 overlay2 的区别
- 三、镜像层文件查找与 chainID 计算
-
- 1. 查找镜像指定层文件内容(思路)
- 2. 完整操作流程
-
- 步骤 1:获取镜像短 ID
- 步骤 2:通过短 ID 获取镜像长 ID
- 步骤 3:根据镜像长 ID 获取镜像分层 ID
- 步骤 4:通过分层 ID 获取分层缓存 ID
- 步骤 5:查看该分层实际文件存储目录
- 3. 镜像底层与中间层查找规则
- 4. 中间层 chainID 计算示例
- 四、容器与镜像的关系(Nginx Overlay 演示)
-
- 1. 启动 Nginx 容器
- 2. 查看容器 overlay 挂载信息
- 3. Overlay 联合文件系统四层结构
- 4. 查看只读层短 ID
- 5. 容器内写文件测试
容器镜像与 Overlay2 存储
一、容器镜像概述
1. Docker 镜像
- Docker 镜像是只读的容器模板,是容器运行的基础。
- 为容器提供静态文件系统运行环境(rootfs)。
- 镜像 = 容器的「静止状态」;容器 = 镜像的「运行状态」。
2. 联合文件系统(UnionFS)
- 联合文件系统是实现「联合挂载」技术的文件系统。
- 联合挂载可以在一个挂载点同时挂载多个文件系统,将挂载点原目录与被挂载内容整合,最终呈现整合后的各层文件和目录。
- Docker 镜像基于该技术实现分层下载与分层存储。
二、Docker Overlay2 存储驱动
1. 存储驱动说明
容器文件系统有多种存储驱动实现:aufs(联合文件系统)、devicemapper(设备映射)、overlay、overlay2 等。本文以 overlay2 为例说明。
2. 核心概念
3. Overlay2 分层结构
- lowerdir:只读镜像层,存放基础镜像文件(示例 file1、file2、file3)。
- upperdir:容器读写层,保存容器运行时的修改、新增文件(示例中覆盖 file2、新增 file4)。
- merged:联合挂载后的统一视图,容器内可见整合后的完整文件(file1~file4)。
原理:底层只读镜像层 + 上层可写容器层,合并对外提供完整文件系统。
4. 元数据(Metadata)
元数据即文件的属性信息,包括:
- 名称(如 abc)
- 文件大小
- 文件权限
- 创建时间
- 文件类型
- 文件所有者
5. 为什么下载慢、删除快?
- 下载慢:需要完整拉取镜像各层数据,数据量大。
- 删除快:删除的只是数据的元数据(索引),只要未被覆盖写入,数据就不易真正丢失,因此删除很快。
6. OverlayFS 与 overlay2 的区别
root@harbor:~# docker info | grep overlay
Storage Driver: overlayfs
Network: bridge host ipvlan macvlan null overlay
思考:为什么显示的不是 overlay2?overlayfs 和 overlay2 有什么区别?
简单来说:
- OverlayFS:Linux 内核中的一个文件系统,提供联合挂载(union mount)功能。
- overlay2:Docker 基于 OverlayFS 实现的一个存储驱动(storage driver)。
docker info 中 Storage Driver: overlayfs 表示 Docker 正在使用基于 OverlayFS 的存储驱动,实际上就是 overlay2。
核心区别:overlay(旧版)vs overlay2(新版)
| 镜像层支持 | 仅支持单层 lowerdir,多层时靠目录 + 硬链接模拟,效率低 | 原生支持多层 lowerdir,最多 128 层 |
| Inode 利用 | 效率低,容器/镜像多时易耗尽 inode | 效率高,显著减少 inode 压力 |
| 内核要求 | 3.18+ | 4.0+(RHEL/CentOS 7 需 3.10.0-514+) |
| 稳定性与性能 | 早期实现,相对有限 | 更好,尤其多层镜像与频繁写操作 |
| 官方推荐 | 不推荐用于生产 | 首选、默认 |
为什么新版显示 overlayfs?
较新版本 Docker(尤其是使用较新 containerd 的版本)术语发生了变化:官方将 Linux 内核驱动称为 OverlayFS,将 Docker 存储驱动称为 overlay2。从 Docker Engine 29.0 起,overlay2 被视为「经典(legacy)」驱动,被新的 overlayfs containerd snapshotter 取代,因此新系统显示 Storage Driver: overlayfs 是正常且符合预期的。
小结:
三、镜像层文件查找与 chainID 计算
1. 查找镜像指定层文件内容(思路)
2. 完整操作流程
步骤 1:获取镜像短 ID
docker images
步骤 2:通过短 ID 获取镜像长 ID
路径:/var/lib/docker/image/overlay2/
cat repositories.json | grep 短ID
步骤 3:根据镜像长 ID 获取镜像分层 ID
路径:/var/lib/docker/image/overlay2/imagedb/content/sha256/长ID
cat /var/lib/docker/image/overlay2/imagedb/content/sha256/长ID
步骤 4:通过分层 ID 获取分层缓存 ID
路径:layerdb/sha256/分层ID/cache-id
cat layerdb/sha256/分层ID/cache-id
步骤 5:查看该分层实际文件存储目录
路径:/var/lib/docker/overlay2/缓存ID/diff/
ls /var/lib/docker/overlay2/缓存ID/diff/
3. 镜像底层与中间层查找规则
查找目标:找到镜像层最底层,再依次查找各中间层。
Docker 内容寻址机制:Docker 依据文件内容索引镜像与镜像层,通过 rootfs 中的 diff_id 计算 chainID,依靠 chainID 查询 layer 信息,最终定位镜像层文件。
chainID 计算规则:
查看镜像 diff_ids 示例:
cat /var/lib/docker/image/overlay2/imagedb/content/sha256/22bd1541745359072c06a72a23f4f6c52dbb685424e0d5b29008ae4eb2683698
rootfs 分层 diff_ids 字段示例:
"rootfs":{"type":"layers","diff_ids":[
"sha256:1bb35e8b4de116e84b2ccf614cce4e309b6043bf2cd35543d8394edeaeb587e3",
"sha256:cff9e7c67fbb49f4a3d39a66187b50cb525ac501d92b8a921b6877270b6f4ae5",
"sha256:c29414fee8ae39b813dd7a744a2acf3e6d755fc70b2ea2bff9b707171a9fd41b",
"sha256:05afaee498cfc72f71eb89da7586190efa6370883fbb51f1f8e1aab1942aa7a0",
"sha256:2649de4780441086779fb6d6f7645e257f90fb1729b0a36898b8b5faba0f7d86",
"sha256:215876b361535855516505977b46790e7f44f693f7473c1efaf8b2c7dac4f241a",
"sha256:f3cecf76da4f34560262476c610533206d0f8e3344f896cc2fb0e59efcc0516a"
]}
数组内顺序自上而下为:底层 → 各中间层 → 顶层。
4. 中间层 chainID 计算示例
以「第 2 个中间层」为例:
分层数据
- 底层 diff_id:sha256:1bb35e8b4de116e84b2ccf614cce4e309b6043bf2cd35543d8394edeaeb587e3
- 第 2 个中间层 diff_id:sha256:cff9e7c67fbb49f4a3d39a66187b50cb525ac501d92b8a921b6877270b6f4ae5
计算逻辑:拼接上一层 chainID(底层 diff_id)与当前层 diff_id,对拼接字符串做 sha256 哈希,得到当前层 chainID。
实操命令
echo -n "sha256:1bb35e8b4de116e84b2ccf614cce4e309b6043bf2cd35543d8394edeaeb587e3 sha256:cff9e7c67fbb49f4a3d39a66187b50cb525ac501d92b8a921b6877270b6f4ae5" | sha256sum –
四、容器与镜像的关系(Nginx Overlay 演示)
1. 启动 Nginx 容器
# 后台运行 nginx 镜像
docker run -d nginx:latest
# 查看运行中的 nginx 容器
docker ps | grep nginx
输出示例容器 ID:381b3e88e209
2. 查看容器 overlay 挂载信息
mount | grep overlay
挂载字段拆解:
3. Overlay 联合文件系统四层结构
4. 查看只读层短 ID
重点查看容器 lowerdir 镜像只读层:
ls /var/lib/docker/overlay2/l/
输出一堆层短 ID 字符串。
cd /var/lib/docker/overlay2/l/
# 第 1 个短 ID 是初始化层,名称对应目录带 -init
ls -l IJGJLS2P7M4G6NRVRHZHT72YZQ
lrwxrwxrwx 1 root root 77 7月 19 21:44 IJGJLS2P7M4G6NRVRHZHT72YZQ -> ../9f48c74e6e6b93df22db6474adc950b3bb1dd00cccf68df16f44cda1b1aa3635c-init/diff
ls -l 2J0F24V5EE3R50XZNGLKVPWW3E
lrwxrwxrwx 1 root root 72 7月 18 07:23 2J0F24V5EE3R50XZNGLKVPWW3E -> ../a18c4a00e8aa368aaf13844e20213bb4029ef4cf8f315dc3d00fb5c9f9b6f33c/diff
目录内文件均为软链接,指向各层真实 diff 目录;带 -init 的为容器初始化底层,其余为普通镜像只读层。
- IJGJLS2P7M4G6NRVRHZHT72YZQ 映射容器的初始化层 init,该层包含与容器配置相关的文件内容,是只读的。
- 其余 ID 分别对应镜像各层文件内容,映射到镜像层的 diff 目录。
5. 容器内写文件测试
启动容器后,Docker 将镜像内容 mount 到容器中。若在容器内修改文件,是否会影响镜像?
结论:由 overlay2 分层结构可知,容器内写文件会写入 upperdir(读写层),不会修改 lowerdir 底层镜像。
注:本次演示容器只有一层镜像,因此展示较为直观。
网硕互联帮助中心





评论前必须登录!
注册