控制台 退出登录

镜像层与可写层原理


镜像层 = 只读的"模板"(所有容器共享)
可写层 = 每个容器独有的"草稿纸"(容器删除就没了)

单个容器的文件系统结构


容器看到的文件系统 (rootfs)
         ↓
    ┌─────────────────┐
    │   可写层         │  ← 容器运行时的修改都在这
    │  (Container)    │     (读写,容器独有)
    ├─────────────────┤
    │   镜像层3        │  ← 只读,所有用这个镜像的
    │  (Layer 3)      │     容器共享
    ├─────────────────┤
    │   镜像层2        │  ← 只读,共享
    │  (Layer 2)      │
    ├─────────────────┤
    │   镜像层1        │  ← 只读,共享
    │  (Layer 1)      │
    └─────────────────┘
         ↓
    物理存储位置

场景:运行3个Nginx容器


物理存储上:

/var/lib/containerd/
├── 镜像层存储/
│   ├── layer1: nginx基础层 (100MB)      ← 只有1份
│   ├── layer2: nginx配置层 (10MB)       ← 只有1份
│   └── layer3: nginx应用层 (50MB)       ← 只有1份
│
└── 可写层存储/
    ├── 容器A的可写层 (5MB)              ← 容器A独有
    ├── 容器B的可写层 (3MB)              ← 容器B独有
    └── 容器C的可写层 (8MB)              ← 容器C独有

总占用 = 160MB(镜像层) + 16MB(可写层) = 176MB
如果没有分层,需要: 160MB × 3 = 480MB

容器内的操作

bash
# 在容器A中操作
docker exec -it 容器A bash

# 1. 读取文件 /usr/share/nginx/index.html
cat /usr/share/nginx/index.html
# → 从镜像层读取(所有容器看到的一样)

# 2. 修改文件
echo "Hello A" > /usr/share/nginx/index.html
# → 触发 Copy-on-Write (写时复制)
# → 文件从镜像层复制到容器A的可写层
# → 修改只在容器A的可写层

# 3. 新建文件
echo "test" > /tmp/myfile.txt
# → 直接写入容器A的可写层

其他容器不受影响

bash
# 在容器B中
cat /usr/share/nginx/index.html
# → 仍然读取镜像层的原始文件
# → 看不到容器A的修改

特性

镜像层 (Image Layers)

可写层 (Container Layer)

权限

只读 (Read-Only)

可读写 (Read-Write)

共享性

所有容器共享

每个容器独有

位置

/var/lib/containerd/io.containerd.content.v1.content/

/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/

生命周期

镜像删除才消失

容器删除就消失

大小

固定(镜像大小)

动态增长

内容

镜像打包的文件

容器运行时产生的数据

修改

不能修改

可以修改

五、写时复制(Copy-on-Write)机制

工作原理


1. 容器要修改 /etc/nginx/nginx.conf

2. 检查文件位置
   ┌─────────────────────────┐
   │ 文件在镜像层?           │
   │ Yes → 触发COW           │
   └──────────┬──────────────┘
              ↓
   ┌──────────────────────────┐
   │ 复制文件到可写层          │
   └──────────┬───────────────┘
              ↓
   ┌──────────────────────────┐
   │ 在可写层修改文件          │
   └──────────┬───────────────┘
              ↓
   ┌──────────────────────────┐
   │ 容器看到的是可写层的版本  │
   │ 镜像层的原文件被"遮住"    │
   └──────────────────────────┘

本文采用 CC BY-NC-SA 4.0 协议发布

相关文章

鹊桥计划

鹊桥计划

日志模板提取与 Drain 算法

日志模板提取与 Drain 算法

Thin Pool

Thin Pool