Docker 三大核心技术对比
1. 作用对比
┌─────────────────────────────────────────────────────────┐
│ Docker 三大核心技术的作用 │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 1. Namespace(隔离) │ │
│ │ │ │
│ │ 作用:隔离进程的视图 │ │
│ │ • PID Namespace - 隔离进程 ID │ │
│ │ • Network Namespace - 隔离网络 │ │
│ │ • Mount Namespace - 隔离文件系统挂载点 │ │
│ │ • IPC Namespace - 隔离进程间通信 │ │
│ │ • UTS Namespace - 隔离主机名 │ │
│ │ • User Namespace - 隔离用户 ID │ │
│ │ • Cgroup Namespace - 隔离 Cgroup 视图 │ │
│ │ │ │
│ │ 类比:给每个容器一个"独立的世界" │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 2. Cgroup(资源限制) │ │
│ │ │ │
│ │ 作用:限制资源使用 │ │
│ │ • CPU 限制 - 限制 CPU 使用率 │ │
│ │ • 内存限制 - 限制内存使用 │ │
│ │ • IO 限制 - 限制磁盘 IO │ │
│ │ • 进程数限制 - 限制进程数量 │ │
│ │ │ │
│ │ 类比:给每个容器分配"资源配额" │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 3. OverlayFS(文件系统) │ │
│ │ │ │
│ │ 作用:实现镜像层和容器层的联合挂载 │ │
│ │ • 镜像层 - 只读层(共享) │ │
│ │ • 容器层 - 可写层(每个容器独立) │ │
│ │ • 联合挂载 - 合并多个层为一个视图 │ │
│ │ • Copy-on-Write - 修改时才复制 │ │
│ │ │ │
│ │ 类比:给每个容器一个"独立的文件系统视图" │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ 关键区别: │
│ • Namespace = 隔离(让容器看不到其他容器) │
│ • Cgroup = 限制(让容器不能无限使用资源) │
│ • OverlayFS = 存储(让容器有独立的文件系统) │
└─────────────────────────────────────────────────────────┘
2. OverlayFS 的具体作用
问题:为什么需要 OverlayFS?
┌─────────────────────────────────────────────────────────┐
│ 没有 OverlayFS 的问题 │
│ │
│ 场景:100 个容器都使用 ubuntu:20.04 镜像 │
│ │
│ 方案 1:每个容器完整复制镜像 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Container│ │ Container│ │ Container│ │
│ │ 1 │ │ 2 │ │ ... │ │
│ │ │ │ │ │ │ │
│ │ 完整镜像 │ │ 完整镜像 │ │ 完整镜像 │ │
│ │ 500MB │ │ 500MB │ │ 500MB │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ 总存储:100 × 500MB = 50GB ❌ 浪费空间! │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 使用 OverlayFS 的解决方案 │
│ │
│ 场景:100 个容器都使用 ubuntu:20.04 镜像 │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 镜像层(只读,共享) │ │
│ │ ubuntu:20.04 (500MB) │ │
│ │ └── /bin, /lib, /usr, ... │ │
│ └──────────────────────────────────────────────────┘ │
│ ↑ │
│ │ 共享 │
│ ┌───────────┼───────────┐ │
│ │ │ │ │
│ ┌───────▼───┐ ┌─────▼─────┐ ┌──▼──────┐ │
│ │ Container │ │ Container │ │Container│ │
│ │ 1 │ │ 2 │ │ 100 │ │
│ │ │ │ │ │ │ │
│ │ 容器层 │ │ 容器层 │ │ 容器层 │ │
│ │ 10MB │ │ 10MB │ │ 10MB │ │
│ └──────────┘ └──────────┘ └─────────┘ │
│ │
│ 总存储:500MB + (100 × 10MB) = 1.5GB ✅ 节省空间! │
└─────────────────────────────────────────────────────────┘
3. 三者如何协同工作
┌─────────────────────────────────────────────────────────┐
│ Docker 容器启动时的完整流程 │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 1. OverlayFS(文件系统) │ │
│ │ │ │
│ │ • 创建容器层(可写层) │ │
│ │ • 挂载镜像层(只读层) │ │
│ │ • 联合挂载到 merged 目录 │ │
│ │ │ │
│ │ 结果:容器有独立的文件系统视图 │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 2. Namespace(隔离) │ │
│ │ │ │
│ │ • 创建 PID Namespace │ │
│ │ • 创建 Network Namespace │ │
│ │ • 创建 Mount Namespace │ │
│ │ • 创建 IPC Namespace │ │
│ │ • 创建 UTS Namespace │ │
│ │ • 创建 User Namespace │ │
│ │ │ │
│ │ 结果:容器有独立的进程、网络、文件系统视图 │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 3. Cgroup(资源限制) │ │
│ │ │ │
│ │ • 创建 Cgroup 组 │ │
│ │ • 设置 CPU 限制 │ │
│ │ • 设置内存限制 │ │
│ │ • 设置 IO 限制 │ │
│ │ │ │
│ │ 结果:容器资源使用受限 │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 4. 启动容器进程 │ │
│ │ │ │
│ │ • 在 Namespace 中运行 │ │
│ │ • 使用 OverlayFS 文件系统 │ │
│ │ • 受 Cgroup 限制 │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
4. 实际例子对比
例子:运行一个 Redis 容器
docker run -d --name redis redis:latest
OverlayFS 做了什么:
┌─────────────────────────────────────────────────────────┐
│ OverlayFS 的工作 │
│ │
│ 1. 挂载镜像层(只读) │
│ /var/lib/docker/overlay2/<image-id>/diff │
│ ├── /usr/local/bin/redis-server │
│ ├── /etc/redis.conf │
│ └── ... │
│ │
│ 2. 创建容器层(可写) │
│ /var/lib/docker/overlay2/<container-id>/diff │
│ └── (空,等待写入) │
│ │
│ 3. 联合挂载 │
│ /var/lib/docker/overlay2/<container-id>/merged │
│ ├── /usr/local/bin/redis-server ← 来自镜像层 │
│ ├── /etc/redis.conf ← 来自镜像层 │
│ └── /data/redis.rdb ← 写入容器层 │
│ │
│ 结果:容器看到完整的文件系统,但只存储修改的部分! │
└─────────────────────────────────────────────────────────┘
5. OverlayFS 工作原理
目录结构
/var/lib/docker/overlay2/
├── <layer-id>/ # 镜像层(只读)
│ └── diff/ # 镜像文件
│
├── <container-id>/ # 容器层(可写)
│ ├── diff/ # 容器修改的文件(upperdir)
│ ├── work/ # 工作目录(workdir)
│ ├── merged/ # 合并视图(挂载点)
│ ├── lower # 镜像层列表文件
│ └── link # 符号链接 ID
│
└── l/ # 符号链接目录
└── <link-id> -> ../<container-id>/diff
三层结构
┌─────────────────────────────────────────┐
│ merged/ (容器看到的完整文件系统) │
│ ├── /usr/local/bin/redis-server │
│ ├── /etc/redis.conf │
│ └── /data/redis.rdb │
└─────────────────────────────────────────┘
↑
│ OverlayFS 合并
│
┌─────────────────────────────────────────┐
│ upperdir (容器层 - 可写) │
│ └── /data/redis.rdb ← 容器修改的文件 │
└─────────────────────────────────────────┘
↑
│ 叠加在
│
┌─────────────────────────────────────────┐
│ lowerdir (镜像层 - 只读,多个层) │
│ ├── layer-9: /usr/local/bin/redis-server│
│ ├── layer-8: /etc/redis.conf │
│ └── ... │
└─────────────────────────────────────────┘