一、用生活类比理解 overlay2 的本质
想象你有一叠透明的画画纸:
最下面一张是「基础画纸」(相当于 Docker 镜像),上面画着固定的图案(程序和系统文件)。
每次在上面盖一张新的「透明纸」(相当于容器的层),你可以在新纸上修改或添加图案,不会破坏下面的纸。
overlay2 就是管理这叠纸的「文件夹」,让所有纸看起来像一张完整的画(容器运行时的文件系统)。
二、overlay2 的核心组成部分及作用
目录结构总览
/var/lib/docker/overlay2/ ├── l # 软链接文件夹,指向具体层的路径 ├── mnt # 容器挂载点,合并所有层的文件 ├── <hash1>/ # 镜像层(只读) │ ├── diff/ # 存储该层的文件变更 │ ├── link # 层的唯一标识 │ └── lower # 记录下层的路径 └── <hash2>/ # 容器层(可写) ├── diff/ # 存储容器运行时的修改 ├── link # 层的唯一标识 ├── lower # 记录所有下层镜像的路径 └── work # 临时工作目录,用于文件修改
关键部分详解
镜像层(只读层):
像图书馆的书,多个容器可以共享同一本书(镜像层),节省空间。容器层(可写层):
像在书上贴便签,容器运行时的修改(如新建文件、修改内容)都存在这里,不影响原书。mnt 目录:
像「魔法桌面」,把所有层的文件合并显示,容器看到的就是这个合并后的文件系统。
三、overlay2 背后的工作原理(流程图)
┌──────────────────────────────────────────────────────────┐ │ 当启动容器时,overlay2 做了这些事: │ ├───────────────────┬──────────────────────────────────────┤ │ 1. 找到镜像的所有只读层(如 A、B、C 层) │ │ ▼ │ │ 2. 创建一个新的可写层 D,用于存储容器的修改 │ │ ▼ │ │ 3. 在 mnt 目录中,用「联合文件系统」把 A+B+C+D 合并成一个 │ │ ▼ │ │ 4. 容器访问的就是这个合并后的文件系统,修改会存在 D 层 │ └──────────────────────────────────────────────────────────┘
联合文件系统原理:
就像叠透明纸,下面的层(镜像)是只读的,上面的层(容器)可以修改。当修改一个文件时:
先把原文件从下层「复制」到上层(称为「写时复制」)
在上层修改这个复制后的文件,下层文件保持不变
四、使用场景举例
多个容器共享同一镜像
场景:运行 10 个 Nginx 容器,每个容器共享同一个 Nginx 镜像层,只需要存储一次镜像文件。
好处:节省磁盘空间,像 10 个人看同一本漫画书,不用每人买一本。
容器快速创建和删除
场景:测试环境中频繁创建、删除容器(如 CI/CD 部署)。
原理:删除容器只需要删除可写层,镜像层不受影响,像撕掉便签,书还在。
数据持久化
场景:容器中数据库的数据需要保存,即使容器删除也不丢失。
做法:把数据目录挂载到宿主机(绕过 overlay2 的层机制),像把重要的便签单独贴在书桌抽屉里。
五、底层技术关键点(用代码比喻)
虽然 overlay2 是用 C 语言写的,但可以用 PHP 逻辑理解核心思想:
// 模拟 overlay2 的核心逻辑(非实际代码,仅用于理解)class Overlay2 { // 存储所有层的信息 private $layers = []; // 添加一个镜像层(只读) public function addImageLayer($layerHash, $parentLayers) { $this->layers[$layerHash] = [ 'type' => 'read-only', // 标记为只读 'parent' => $parentLayers, // 记录下层是谁 'path' => "/var/lib/docker/overlay2/$layerHash/diff" // 层的文件路径 ]; echo "创建镜像层 {$layerHash},像添加一本新漫画书\n"; } // 创建容器的可写层 public function createContainerLayer($containerId, $imageLayers) { $layerHash = md5(uniqid()); // 生成唯一标识 $this->layers[$layerHash] = [ 'type' => 'read-write', // 标记为可写 'parent' => $imageLayers, // 下层是所有镜像层 'path' => "/var/lib/docker/overlay2/$layerHash/diff", 'work_path' => "/var/lib/docker/overlay2/$layerHash/work" // 临时工作目录 ]; // 创建软链接,方便快速找到层 symlink($this->layers[$layerHash]['path'], "/var/lib/docker/overlay2/l/$containerId"); echo "为容器 {$containerId} 创建可写层 {$layerHash},像准备一张空白便签\n"; } // 合并所有层,生成容器看到的文件系统 public function mountContainer($containerId, $mountPath) { // 获取所有下层(镜像层)的路径 $lowerPaths = []; foreach ($this->layers as $hash => $layer) { if (in_array($hash, $this->layers[$containerId]['parent'])) { $lowerPaths[] = "lowerdir={$layer['path']}"; } } // 添加当前可写层的路径 $lowerPaths[] = "upperdir={$this->layers[$containerId]['path']}"; $lowerPaths[] = "workdir={$this->layers[$containerId]['work_path']}"; // 用联合文件系统挂载(实际是调用 Linux 的 mount 命令) $command = "mount -t overlay overlay -o " . implode(',', $lowerPaths) . " $mountPath"; exec($command); echo "把所有层合并到 {$mountPath},像把所有透明纸叠在一起\n"; } // 当容器修改文件时(写时复制) public function modifyFile($containerId, $filePath) { $layer = $this->layers[$containerId]; $sourceLayer = $this->findFileSourceLayer($filePath, $layer['parent']); if ($sourceLayer) { // 从下层复制文件到当前可写层 $sourceFile = "{$sourceLayer['path']}/" . substr($filePath, 1); $targetFile = "{$layer['path']}/" . substr($filePath, 1); copy($sourceFile, $targetFile); echo "从下层复制文件到可写层,像把书上的内容抄到便签\n"; } else { // 文件是新建的,直接存在可写层 touch($targetFile); echo "新建文件,存在便签上\n"; } } // 查找文件在哪个下层 private function findFileSourceLayer($filePath, $parentHashes) { foreach ($parentHashes as $hash) { $layerPath = "{$this->layers[$hash]['path']}/" . substr($filePath, 1); if (file_exists($layerPath)) { return $this->layers[$hash]; } } return false; }}
六、思维导图:overlay2 的全貌
/var/lib/docker/overlay2 的世界 ├── 核心作用:管理容器和镜像的文件层,像叠透明纸 ├── 组成部分: │ ├── 镜像层(只读):多个容器共享的「基础画纸」 │ ├── 容器层(可写):每个容器独有的「便签纸」 │ ├── mnt 目录:合并所有层的「魔法桌面」 │ └── work 目录:临时修改文件的「草稿本」 ├── 工作原理: │ ├── 联合文件系统:把多层文件合并显示 │ ├── 写时复制:修改时先复制到可写层,不影响下层 │ └── 软链接:快速找到层的路径,像书签 ├── 使用场景: │ ├── 多容器共享镜像:节省空间,像多人看同一本书 │ ├── 快速创建容器:只加便签,不复制整本书 │ └── 数据持久化:重要数据单独存,不放在便签上 └── 底层技术: ├── Linux 内核的 overlay 或 overlay2 驱动 ├── mount 命令实现文件系统挂载 └── 写时复制(Copy-on-Write)机制
七、总结:透过现象看本质
overlay2 就像一个「文件层管理员」,它的核心魔法是:
用「透明纸叠放」的方式管理镜像和容器的文件,让它们共享底层资源又互不干扰;
当你修改文件时,它偷偷把修改内容放到最上面的「便签纸」上,不破坏下面的「原书」;
最终呈现给容器的,是所有纸叠在一起的「完整画面」,但实际存储的是每一层的差异,节省了大量空间。
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://hqyman.cn/post/11590.html 非本站原创文章欢迎转载,原创文章需保留本站地址!


休息一下~~