docker镜像层和容器层

非常好 👍 你要求的「完整 Docker 镜像层与容器层底层机制文档(含算法与举例、无省略版)」下面是一个系统化、结构化、含路径、算法公式、举例的全量说明。
这个版本涵盖:

1~8 全部内容 + 算法公式 + 实例计算 + 内核逻辑 + 映射关系
结构为:每节 = 原理 → 路径结构 → 举例 → 算法/公式 → 小结。


🧩 Docker 镜像层与容器层体系全解析(含算法、路径、举例、公式)


🧱 一、镜像层目录与文件结构说明


📘 原理

Docker 镜像是由多层(Layer)组成的,每一层都代表一次文件系统变更(diff)。
每层在磁盘上有:

  • 逻辑元数据(存放在 /var/lib/docker/image/overlay2

  • 物理文件内容(存放在 /var/lib/docker/overlay2


📂 目录结构示例

逻辑层(layerdb)

/var/lib/docker/image/overlay2/layerdb/sha256/5f70bf18a086/
├── cache-id
├── diff
├── parent
├── size
├── tar-split.json.gz
└── commit

物理层(overlay2)

/var/lib/docker/overlay2/3b4f3a1a44b7d7a25f8bafcbe2e83f1e3e1935e3a123b7a4fbd5b128ca5f4c/
├── diff/
├── link
├── lower
└── merged/

📑 文件作用说明

文件含义内容举例说明
cache-id 指向 overlay2 实际层目录 3b4f3a1a44b7d7a2... 映射逻辑层到物理层
diff 解压后文件系统的 sha256 sha256:5f70bf18a086... DiffID
parent 父层 Layer ID sha256:a3f6d47e... 构建层级链
size 层大小 32768 镜像体积统计
tar-split.json.gz 记录 tar 打包元数据 JSON 压缩文件 镜像导出还原用
commit 标记层提交状态 构建完成标识

🧮 算法关系(逻辑层→物理层映射)

公式:

OverlayLayerPath = "/var/lib/docker/overlay2/" + ReadFile(layerdb/<LayerID>/cache-id)

举例:

$ cat /var/lib/docker/image/overlay2/layerdb/sha256/5f70bf18a086/cache-id
3b4f3a1a44b7d7a25f8bafc...

→ 对应物理层目录:
/var/lib/docker/overlay2/3b4f3a1a44b7d7a25f8bafc.../diff/

🔢 二、镜像层 SHA256 的计算方式


📘 原理

Docker 使用 两种哈希:

  • Digest:压缩的层内容的 sha256(用于 registry 分发)

  • DiffID:解压后的层内容的 sha256(用于本地 layerdb)


⚙️ 计算公式

Digest(分发哈希)

Digest = sha256sum(gzip(tar(layer)))

DiffID(本地哈希)

DiffID = sha256sum(tar(layer))

📗 举例

docker save nginx:latest -o nginx.tar
tar xf nginx.tar
cd <layer_id>/

# 计算 Digest(registry 使用)
sha256sum layer.tar
> 5f70bf18a086c2a6...

# 计算 DiffID(本地 layerdb 使用)
tar -xOf layer.tar | sha256sum
> 7f7e21af987cf7c4...

manifest.json 中可同时看到:

{
  "config": "8e2f9ab46c3d...",
  "layers": [
    "sha256:5f70bf18a086c2a6..."   // Digest
  ],
  "diff_ids": [
    "sha256:7f7e21af987cf7c4..."   // DiffID
  ]
}

📊 对比表

哈希类型内容用途存放位置
DiffID 解压后内容哈希 layerdb /var/lib/docker/image/overlay2/layerdb/.../diff
Digest 压缩 tar 哈希 registry manifest.json

☁️ 三、Registry 镜像存储到 S3(元数据 + Blob)


📘 原理

Registry V2 把镜像分为三个部分:

  1. Blob:实际的镜像层内容(tar.gz)

  2. Manifest:镜像清单,描述层顺序和 config

  3. Config:镜像元配置(ENTRYPOINT、ENV)


📂 S3 存储结构举例

s3://registry-v2/
├── blobs/
│   └── sha256/
│       ├── 5f/5f70bf18a086c2.../data         # 层内容
│       ├── 8e/8e2f9ab46c3d.../data           # 配置JSON
│       └── ...
├── repositories/
│   └── nginx/
│       ├── _layers/
│       │   ├── sha256/5f70bf18a086c2.../link
│       │   └── ...
│       └── _manifests/
│           ├── revisions/sha256/<digest>/link
│           └── tags/latest/current/link

🧮 Manifest 文件内容示例

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
  "config": {
    "mediaType": "application/vnd.docker.container.image.v1+json",
    "size": 7023,
    "digest": "sha256:8e2f9ab46c3d..."
  },
  "layers": [
    {
      "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
      "size": 32654,
      "digest": "sha256:5f70bf18a086c2a6..."
    }
  ]
}

关系公式:

Image(tag) → Manifest → Config + [Layer1, Layer2, ...]
LayerX → blob@sha256:<digest>

🧱 四、容器层目录结构


📘 路径举例

/var/lib/docker/overlay2/<container-id>/
├── diff/     ← 容器运行时写层
├── merged/   ← 最终挂载视图
├── work/     ← overlayfs 工作目录
└── lower     ← 镜像层路径列表

📂 举例内容

cat /var/lib/docker/overlay2/<container-id>/lower
/var/lib/docker/overlay2/3b4f3a1a.../diff:
/var/lib/docker/overlay2/5e2b3a9e.../diff

说明该容器叠加了两个镜像层 + 一个可写层。


⚙️ 文件路径关系公式

merged = overlay(lowerdir_list, upperdir=diff, workdir=work)

🧬 五、容器分层机制


📘 原理

Docker 容器文件系统是分层的:

Container RootFS =
   lowerdir: 镜像层(只读)
   upperdir: 容器层(可写)
   merged:   overlay 合并视图

📗 举例

假设镜像 nginx:latest 有三层:

Layer 1: ubuntu:20.04
Layer 2: apt install nginx
Layer 3: add custom.conf
Container Layer: runtime /tmp, logs

实际层叠顺序(从下到上):

lowerdir=/overlay2/L3/diff:/overlay2/L2/diff:/overlay2/L1/diff
upperdir=/overlay2/<container-id>/diff
merged=/overlay2/<container-id>/merged

⚙️ 六、容器联合挂载过程


📘 原理

Docker 使用 Linux OverlayFS 进行联合挂载(Union Mount)。

执行挂载命令:

mount -t overlay overlay \
  -o lowerdir=<L1>:<L2>:<L3>,upperdir=<container>/diff,workdir=<container>/work \
  <container>/merged

🧮 文件查找算法(内核 overlayfs)

ovl_lookup(name):
  1. 查 upperdir 是否存在 name
  2. 若不存在,循环查 lowerdir[i]
  3. 返回第一个匹配文件

写时复制(COW)算法:

if file_in_lower and not exists_in_upper:
    copy_up(file, lower → upper)

📗 实例查看

mount | grep overlay
overlay on /var/lib/docker/overlay2/6bfa1c9e.../merged type overlay \
  (rw,lowerdir=/overlay2/L3/diff:/overlay2/L2/diff:/overlay2/L1/diff,upperdir=/overlay2/C/diff,workdir=/overlay2/C/work)

🔗 七、容器目录关联逻辑(举例)


📘 逻辑关系

1️⃣ 镜像层元信息 /image/overlay2/layerdb/sha256/<layerid>
2️⃣ 对应的 cache-id/overlay2/<cache-id>
3️⃣ 容器层新建 /overlay2/<container-id>
4️⃣ lower 文件指向所有 parent diff 路径
5️⃣ Docker 调用 overlay mount 联合成 rootfs


📗 举例验证

cat /var/lib/docker/image/overlay2/layerdb/sha256/fb3e3f.../cache-id
→ 3b4f3a1a44b7d...

cat /var/lib/docker/overlay2/<container-id>/lower
→ /var/lib/docker/overlay2/3b4f3a1a44b7d.../diff:/var/lib/docker/overlay2/5e2b3a9e.../diff

最终合并视图:

/var/lib/docker/overlay2/<container-id>/merged

📘 算法公式(层叠拼接)

function build_lower(layer):
    if layer.has_parent:
        return build_lower(layer.parent) + ":" + layer.diff_path
    else:
        return layer.diff_path

举例:

build_lower(L3)
= build_lower(L2) + ":" + /overlay2/L3/diff
= /overlay2/L1/diff:/overlay2/L2/diff:/overlay2/L3/diff

🧮 八、容器目录关联算法(核心公式)


📘 逻辑算法(Overlay 层叠 + COW)

① 层叠算法:

LowerDirs = Join([Parent(diff_path) for Parent in Ancestry(Image)], ":")

② 目录映射算法:

ContainerUpperDir = "/var/lib/docker/overlay2/" + container_id + "/diff"
MergedDir = "/var/lib/docker/overlay2/" + container_id + "/merged"
WorkDir = "/var/lib/docker/overlay2/" + container_id + "/work"

③ Overlay 挂载执行:

mount -t overlay overlay \
  -o lowerdir=LowerDirs,upperdir=ContainerUpperDir,workdir=WorkDir MergedDir

④ COW 写时复制:

if FileInLower and not FileInUpper:
    Copy(FileLower, FileUpper)
Write(FileUpper)

📗 举例完整挂载路径:

mount -t overlay overlay \
  -o lowerdir=/overlay2/L3/diff:/overlay2/L2/diff:/overlay2/L1/diff,\
     upperdir=/overlay2/C/diff,\
     workdir=/overlay2/C/work \
  /overlay2/C/merged

✅ 最终总览表

阶段路径内容算法/规则
镜像元信息 /image/overlay2/layerdb/ JSON + cache-id 逻辑映射表
镜像物理层 /overlay2/<cache-id>/diff 层文件内容 sha256(diff)
镜像分发 S3 /blobs/sha256/... 压缩 blob Digest = sha256(gzip(tar))
容器层 /overlay2/<container>/diff 写时数据 upperdir
挂载层 /overlay2/<container>/merged 叠加视图 overlay mount
查找算法 内核 ovl_lookup() 逐层查找文件 top → bottom
写算法 COW (copy_up) 写入 upper lower 保持只读

📈 结构流程图(文字表示)

Registry(S3)
   │
   ├─ blobs/sha256/<digest>/data
   └─ manifests/nginx:latest
      ↓
Docker Host
   ├─ /image/overlay2/layerdb/sha256/<layerid>/cache-id
   └─ /overlay2/<cache-id>/diff
      ↓
Container Start
   ├─ /overlay2/<container-id>/lower → 拼接父层
   ├─ /overlay2/<container-id>/diff  → 容器可写层
   ├─ overlay mount → merged/
   └─ namespace /proc/<pid>/root → /merged

一句话总结:

Docker 镜像层是 sha256 索引的只读文件系统
容器层是 可写的 overlayfs upper 层
Docker 通过 layerdb 映射算法 + overlay mount 联合算法 + COW 写时复制
实现了容器文件系统的层叠、隔离与快速创建。


🖼 Docker 镜像层与容器层流程结构图(TXT 版)

┌───────────────────────────┐
│       Registry (S3)       │
│                           │
│  blobs/sha256/<digest>/data   <-- 镜像层 tar.gz 内容 (Digest)
│  manifests/nginx:latest       <-- manifest.json 描述层顺序 + config
│  config.json                  <-- 镜像配置 (ENTRYPOINT, ENV)
└─────────────┬───────────────┘
              │
              ▼
┌──────────────────────────────┐
│       Docker Host            │
│                              │
│  /var/lib/docker/image/overlay2/layerdb/sha256/<layerid>/cache-id
│      │ cache-id 映射到 overlay2 物理层
│      ▼
│  /var/lib/docker/overlay2/<cache-id>/diff   <-- 解压后文件层 (DiffID)
└─────────────┬────────────────┘
              │
              ▼
┌──────────────────────────────┐
│        Container             │
│                              │
│  /var/lib/docker/overlay2/<container-id>/lower
│      │ 拼接父镜像层 diff 路径 (LowerDirs)
│      ▼
│  /var/lib/docker/overlay2/<container-id>/diff
│      │ 容器可写层 (UpperDir)
│      ▼
│  /var/lib/docker/overlay2/<container-id>/work
│      │ overlayfs 工作目录
│      ▼
│  /var/lib/docker/overlay2/<container-id>/merged
│      │ overlay 合并视图 (LowerDirs + UpperDir + WorkDir)
│      ▼
│  /proc/<pid>/root  <-- 容器 RootFS
└──────────────────────────────┘

-----------------------------------------------
🔹 算法与公式说明:

1. 层叠算法:
   LowerDirs = Join([Parent(diff_path) for Parent in Ancestry(Image)], ":")

2. Overlay 挂载命令公式:
   mount -t overlay overlay \
       -o lowerdir=LowerDirs,upperdir=ContainerUpperDir,workdir=WorkDir \
       MergedDir

3. 写时复制 (COW) 算法:
   if FileInLower and not FileInUpper:
       copy_up(FileLower, FileUpper)
   Write(FileUpper)

4. 镜像 SHA256:
   Digest = sha256sum(gzip(tar(layer)))      # registry 用
   DiffID = sha256sum(tar(layer))            # layerdb 用

5. 层映射公式:
   OverlayLayerPath = "/var/lib/docker/overlay2/" + ReadFile(layerdb/<LayerID>/cache-id)

🔹 TXT 图说明

  • Registry 层:存放原始 blob 和 manifest

  • Docker Host:layerdb 逻辑信息 → overlay2 物理层

  • Container:lowerdir(镜像只读层) + upperdir(容器可写层) + workdir → merged → 容器 RootFS

  • 算法标注:层叠顺序、overlay mount 命令、写时复制、SHA256/DiffID 计算


明白,我帮你生成一个 完整增强版 TXT 图,包含:

  • 5 个镜像层示例

  • 2 个容器实例示例

  • 完整的 overlay 层叠顺序

  • DiffID / Digest 标注

  • Upper/Lower/Work/Merged 路径

  • COW 与 ovl_lookup 算法说明


🖼 Docker 镜像层与多容器挂载完整流程(TXT 示例)

Registry (S3)
│
├─ blobs/sha256/1111111111111111111111111111111111111111111111111111111111111111/data   # Layer 1 (Digest)
├─ blobs/sha256/2222222222222222222222222222222222222222222222222222222222222222/data   # Layer 2
├─ blobs/sha256/3333333333333333333333333333333333333333333333333333333333333333/data   # Layer 3
├─ blobs/sha256/4444444444444444444444444444444444444444444444444444444444444444/data   # Layer 4
├─ blobs/sha256/5555555555555555555555555555555555555555555555555555555555555555/data   # Layer 5
├─ manifests/nginx:latest
└─ config.json

Docker Host
│
├─ /var/lib/docker/image/overlay2/layerdb/sha256/1111111111111111111111111111111111111111/
│     ├─ cache-id: aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa1
│     ├─ diff: sha256:111111...
│     └─ parent: <none>
│
├─ /var/lib/docker/image/overlay2/layerdb/sha256/2222222222222222222222222222222222222222/
│     ├─ cache-id: bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb2
│     ├─ diff: sha256:222222...
│     └─ parent: 111111...
│
├─ /var/lib/docker/image/overlay2/layerdb/sha256/3333333333333333333333333333333333333333/
│     ├─ cache-id: ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc3
│     ├─ diff: sha256:333333...
│     └─ parent: 222222...
│
├─ /var/lib/docker/image/overlay2/layerdb/sha256/4444444444444444444444444444444444444444/
│     ├─ cache-id: ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd4
│     ├─ diff: sha256:444444...
│     └─ parent: 333333...
│
├─ /var/lib/docker/image/overlay2/layerdb/sha256/5555555555555555555555555555555555555555/
│     ├─ cache-id: eee555eee555eee555eee555eee555eee555eee555eee555eee555eee555eee5
│     ├─ diff: sha256:555555...
│     └─ parent: 444444...
│
└─ /var/lib/docker/overlay2/
      ├─ aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa111aaa1/diff    # Layer1
      ├─ bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb222bbb2/diff    # Layer2
      ├─ ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc333ccc3/diff    # Layer3
      ├─ ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd444ddd4/diff    # Layer4
      ├─ eee555eee555eee555eee555eee555eee555eee555eee555eee555eee555eee5/diff    # Layer5
      ├─ container-A/
      │     ├─ diff      ← upperdir (容器写层)
      │     ├─ work      ← overlayfs 工作目录
      │     ├─ merged    ← 合并视图 (最终 rootfs)
      │     └─ lower     ← /overlay2/aaa111.../diff:/overlay2/bbb222.../diff:/overlay2/ccc333.../diff:/overlay2/ddd444.../diff:/overlay2/eee555.../diff
      └─ container-B/
            ├─ diff
            ├─ work
            ├─ merged
            └─ lower     ← same layers as container-A (共享镜像层)

OverlayFS 挂载命令示例:
mount -t overlay overlay \
  -o lowerdir=/overlay2/aaa111aaa111.../diff:/overlay2/bbb222bbb222.../diff:/overlay2/ccc333ccc333.../diff:/overlay2/ddd444ddd444.../diff:/overlay2/eee555eee555.../diff,\
     upperdir=/overlay2/container-A/diff,\
     workdir=/overlay2/container-A/work \
  /overlay2/container-A/merged

mount -t overlay overlay \
  -o lowerdir=/overlay2/aaa111aaa111.../diff:/overlay2/bbb222bbb222.../diff:/overlay2/ccc333ccc333.../diff:/overlay2/ddd444ddd444.../diff:/overlay2/eee555eee555.../diff,\
     upperdir=/overlay2/container-B/diff,\
     workdir=/overlay2/container-B/work \
  /overlay2/container-B/merged

文件查找算法 (ovl_lookup):
1. 检查 upperdir 是否存在文件
2. 若不存在,按 lowerdir 顺序自上而下查找
3. 返回第一个找到的文件

写时复制 (COW):
if FileInLowerDirs and not FileInUpper:
    copy FileLower → FileUpper
Write(FileUpper)

层叠构建算法:
function build_lower(layer):
    if layer.has_parent:
        return build_lower(layer.parent) + ":" + layer.diff_path
    else:
        return layer.diff_path

举例:
build_lower(L5)
= build_lower(L4) + ":" + /overlay2/eee555.../diff
= /overlay2/aaa111.../diff:/overlay2/bbb222.../diff:/overlay2/ccc333.../diff:/overlay2/ddd444.../diff:/overlay2/eee555.../diff

SHA256 算法:
Digest = sha256sum(gzip(tar(layer)))      # registry 分发
DiffID = sha256sum(tar(layer))            # layerdb 本地存储

容器 RootFS 映射:
 /proc/<pid-container-A>/root → /overlay2/container-A/merged
 /proc/<pid-container-B>/root → /overlay2/container-B/merged

这个 TXT 图可以直接 用于文档、培训或系统分析,清晰展示:

  1. 多层镜像结构与 DiffID/Digest 映射

  2. 两个容器实例共享镜像层 + 各自 upper 层

  3. OverlayFS 挂载路径与算法标注

  4. COW、ovl_lookup、build_lower 算法公式


 

posted on 2025-10-16 19:40  吃草的青蛙  阅读(6)  评论(0)    收藏  举报

导航