云安全
云安全概述
阿里云概述
亚马逊AWS概述
云计算导论
云计算概述
云计算的关键技术
虚拟化
分布式文件系统
云存储
数据处理
并行计算
OpenStack
容器
Kubernetes概述
Serverless
Hadoop
云原生
云数据中心
微服务
对象存储OSS
云存储
对象存储
对象文件(Object)
存储桶(存储空间)
通过外网访问OSS
存储桶漏洞
STS访问OSS
权限与访问控制
访问控制
Bucket&RAM Policy
预签名
Docker
01docker概述
02docker安装
03目录结构
04基础操作
05底层原理【理论】
06底层原理【实践】
07DockerFile
08容器反查Dockerfile
09Docker 逃逸
-
+
首页
05底层原理【理论】
从根本上讲,**容器就是一个被严格隔离的进程**。 与虚拟机的本质区别在于: - **虚拟机**:虚拟化的是整个硬件和操作系统;每个VM都有自己的内核,通过Hypervisor层与物理硬件交互;重量级,启动慢,资源占用高。 - **容器**:虚拟化的是操作系统;所有容器共享主机的内核,但通过一系列技术使其拥有独立的文件系统、网络、进程空间等;轻量级,启动快,资源占用极低。 容器的实现主要依赖于Linux内核的三大机制:**命名空间、控制组和联合文件系统**。 ## 命名空间 ### 概述 命名空间(Namespace)是 Linux 内核的一项功能,用于对内核资源进行**隔离**。它使得一组进程可以看到一组特定的资源,而另一组进程可以看到另一组不同的资源。 > 通俗理解 一栋大楼(内核)里的许多独立公寓(命名空间)。每个公寓都有: - 自己的房间号(PID 命名空间) - 自己的业主,不知道其他公寓的业主是谁(User 命名空间) - 自己的网络接口和 IP 地址(Network 命名空间) - 自己的主机名(UTS 命名空间) - 自己的墙,看不到隔壁公寓的装修(Mount 命名空间) 虽然它们共享同一栋大楼的地基和结构(同一个内核),但每个公寓的住户都感觉自己是独享整片资源的。 > 核心目的 隔离: 防止一个命名空间中的进程干扰或窥探另一个命名空间的进程和资源。 虚拟化: 为进程提供一个独立的、仿佛独占系统的视图。这是 Docker、LXC 等容器技术的基石。 > 输出宿主机终端对应的namespace信息 ```bash ## 输出宿主机终端对应的namespace信息,$$表示当前shell本身的PID $ ls -l /proc/$$/ns total 0 lrwxrwxrwx 1 root root 0 Jul 21 06:56 cgroup -> cgroup:[4026531835] lrwxrwxrwx 1 root root 0 Jul 21 06:56 ipc -> ipc:[4026531839] lrwxrwxrwx 1 root root 0 Jul 21 06:56 mnt -> mnt:[4026531840] lrwxrwxrwx 1 root root 0 Jul 21 06:56 net -> net:[4026531957] lrwxrwxrwx 1 root root 0 Jul 21 06:56 pid -> pid:[4026531836] lrwxrwxrwx 1 root root 0 Jul 21 06:56 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Jul 21 06:56 uts -> uts:[4026531838] ``` > 命名空间的类型 Linux 内核实现了多种类型的命名空间,每种隔离一种特定的全局系统资源。 | 命名空间类型 | 隔离的资源 | 内核引入版本 | 说明 | | --------------- | ---------------------------- | ------------ | ------------------------------------------------------------ | | Mount (mnt) | 文件系统挂载点 | 2.4.19 | 进程在不同的挂载命名空间中可以看到不同的文件系统层次结构,拥有独立的根目录 / 和挂载点列表。 | | UTS (uts) | 主机名和 NIS 域名 | 2.6.19 | 允许每个容器拥有自己的主机名(hostname)和域名(domainname)。 | | IPC (ipc) | System V IPC, POSIX 消息队列 | 2.6.19 | 隔离进程间通信资源,如信号量、消息队列和共享内存。不同命名空间的 IPC 对象互不可见。 | | PID (pid) | 进程 ID 号 | 2.6.24 | 在每个 PID 命名空间中,进程都从一个 PID 1(类似 init)开始独立编号。父命名空间可以看到子命名空间的所有进程,但 PID 号不同。 | | Network (net) | 网络设备、IP 地址、端口号等 | 2.6.29 | 每个网络命名空间拥有自己独立的网络栈:网卡、路由表、iptables 规则、端口范围等。 | | User (user) | 用户和组 ID | 3.8 | 允许在命名空间内部和外部使用不同的用户和组 ID。一个进程在命名空间内可以是 root,在命名空间外却是一个普通用户。 | | Cgroup (cgroup) | Cgroup 根目录 | 4.6 | 隔离 Cgroup 信息,使进程只能看到其所属 Cgroup 层次结构中的部分。 | | Time (time) | 系统时钟 | 5.6 | 允许对每个命名空间进行时钟偏移调整,用于容器内的时钟调试或模拟。 | ### unshare 命令 unshare 是 Linux 系统中用于管理命名空间的工具,它允许进程脱离现有的命名空间并创建新的隔离环境。 > 语法 ```txt unshare [选项] [<程序> [<参数>...]] ``` 常用选项 | 选项 | 全称 | 功能描述 | | --------------- | -------- | ------------------------------------------------------------ | | -m | --mount | 创建新的 Mount 命名空间 | | -u | --uts | 创建新的 UTS 命名空间 | | -i | --ipc | 创建新的 IPC 命名空间 | | -n | --net | 创建新的 Network 命名空间 | | -p | --pid | 创建新的 PID 命名空间 | | -U | --user | 创建新的 User 命名空间 | | -C | --cgroup | 创建新的 Cgroup 命名空间 | | -T | --time | 创建新的 Time 命名空间 | | -f | --fork | 执行unshare的进程fork一个新的子进程,在子进程里执行unshare传入参数 | | --mount-proc | | 配合pid使用,在挂载命名空间之前重新挂载 /proc | | --map-root-user | | 在新User命名空间中,将当前用户映射为 root | ### User命名空间 User 命名空间用于隔离用户和组 ID。它允许在命名空间内部使用完全独立的用户 ID 和组 ID 映射,使得一个进程在命名空间内可以是 root 用户,而在宿主系统上只是一个普通用户。 ```txt # 创建 User 命名空间,并映射用户 unshare --user --map-root-user /bin/bash #命令解析 unshare 将当前进程从指定的命名空间中分离,创建新的命名空间 --user 创建新的User命名空间 --map-root-user 用户映射,在当前用户命名空间中将调用者映射为 root (uid 0) 工作机制:创建一个临时的 uid/gid 映射,将外部普通用户映射为内部的 root 作用:在新的User命名空间内部拥有root权限 /bin/bash 在新的命名空间中启动 bash shell ```  使用ps -ef查看 unshare的进程情况。  根据进程号查询对应的进程的uid。  分析: ```txt PID 3570 是sudo命令本身,准备创建新进程 PID 3571 是实际的unshare进程,创建新的User命名空间且启动/bin/bash PID 3572 是启动后的/bin/bash ``` ### PID命名空间 PID NameSpace的作用是来进行进程隔离的。在不同的PID NameSpace中,进程可以拥有的相同的PID号。 ```bash deepmountains@ubuntu:/tmp$ sudo unshare --fork --pid --mount-proc bash # 可以见到的是,新创建的命名空间中没有多少进程。 root@ubuntu:/tmp# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 09:21 pts/0 00:00:00 bash root 5 1 0 09:22 pts/0 00:00:00 ps -ef ``` ### Mnt命名空间 Mount Namespace是Linux内核实现的第一个NameSpace。 它可以用来隔离不同的进程或进程组看到的挂载点。 简单的来讲就是可以实现在不同的进程中看到不同的挂载目录。使用Mount NameSpace可以实现容器内只能看到自己的挂载信息,在容器内的挂在操作不会影响主机的挂载目录。 ```bash # 1.创建一个文件夹,使用tmpfs这种基于内存的文件系统来模拟挂载 $ mkdir /tmp/mnt_isolation # 2.此时我们创建了一个新的mnt命名空间,在这个命名空间中的挂载操作不会影响宿主机的挂在目录。 $ unshare --mount /bin/bash # 3.挂载我们的tmpfs,tmpfs系统临时目录。 $ mount -t tmpfs tmpfs /tmp/mnt_isolation # 4.然后进入/tmp/mnt_isolation创建文件 $ cd /tmp/mnt_isolation && touch linux-mnt-{1..10} $ ls #终端1:新命名空间的终端 linux-mnt-1 linux-mnt-2 linux-mnt-4 linux-mnt-6 linux-mnt-8 linux-mnt-10 linux-mnt-3 linux-mnt-5 linux-mnt-7 linux-mnt-9 # 5.新建立一个shell终端发现并没有创建文件; $ ls /tmp/mnt_isolation/ #终端2:主机的命名空间终端 ``` ### net命名空间 Net NameSpace用来隔离网络设备、IP地址和端口信息。Net NameSpace可以让每个进程拥有自己独立的IP地址,端口和网卡信息。 ```bash #在这里执行的unsafe需要sudo权限,因为是对系统网卡的操作。 deepmountains@ubuntu:/tmp$ sudo unshare --fork --net bash sudo: unable to resolve host ubuntu [sudo] password for deepmountains: root@ubuntu:/tmp# ip addr 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 ``` ### UTS 命名空间 UTS (UNIX Time-sharing System) 命名空间隔离主机名和 NIS 域名。 ```bash #这个其实就比较简单,修改uts命名空间中的主机名不会影响宿主机中的主机名信息。 deepmountains@ubuntu:/root$ sudo unshare --fork --uts bash ``` ### IPC 命名空间 IPC (Inter-Process Communication) NameSpace主要用来隔离进程之间的通讯信息。通常PID和IPC NameSpace命名空间会配合着一起使用,实现同一个命名空间中的进程可以彼此通信,但是不同命名空间的进程不行。 ```bash root@ubuntu:~# su deepmountains deepmountains@ubuntu:/root$ sudo unshare --fork --pid --ipc bash sudo: unable to resolve host ubuntu [sudo] password for deepmountains: ## ipcs命令可以查看主机中管道的信息,当我们创建了一个新的命命空间的时候,你会发现所有的管道都为空。 root@ubuntu:/root# ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status ------ Semaphore Arrays -------- key semid owner perms nsems ``` ## 控制组 ### 概述 Linux 控制组(Control Groups,简称 cgroups)是内核提供的一种**进程资源管理机制**,用于限制、监控、隔离和管理一个或多个进程组对系统资源(CPU、内存、磁盘 IO 等)的使用。 > 核心目标 cgroups 的设计目标是解决 “多进程环境下资源分配与冲突” 的问题,具体包括: - 资源限制(Limiting):为进程组设置资源使用上限(如最大内存、CPU 使用率),防止单个进程耗尽系统资源。 - 资源监控(Accounting):统计进程组对资源的实际使用量(如 CPU 耗时、内存占用),用于计费或性能分析。 - 优先级分配(Prioritization):为不同进程组分配资源优先级(如 CPU 权重、IO 优先级),确保关键服务优先获得资源。 - 隔离(Isolation):隔离进程组的资源访问(如独立的 IO 调度队列),避免相互干扰。 - 控制(Control):对进程组执行操作(如暂停、恢复、冻结),便于管理和故障处理。 ### 架构 cgroups 的架构分为**内核层**和**用户空间层**,通过 “层级结构” 和 “子系统” 实现对进程的资源管理。 > 概念 子系统(Subsystems):又称 “资源控制器”,是内核中负责特定资源管理的模块(如 CPU 控制器、内存控制器)。每个子系统对应一种资源类型,实现对该资源的限制、监控等功能。 控制组(cgroup):一个或多个进程的集合,隶属于某个层级,受该层级附加的子系统管控。每个 cgroup 可以配置资源参数(如内存上限),其下的所有进程均受此配置约束。 层级(Hierarchy):由一系列父子关系的 cgroup 组成的树状结构。一个层级可以附加一个或多个子系统(资源类型),进程通过加入层级中的某个 cgroup,获得该层级子系统的资源管控。 > 核心规则 cgroups 的层级结构是资源管理的核心,需遵循以下规则: 一个层级可附加多个子系统,但一个子系统同一时间只能附加到一个层级(避免资源管理冲突)。 一个进程可加入多个层级(每个层级对应不同资源维度),但在每个层级中,进程只能属于一个 cgroup(即一个进程在 “CPU 层级” 中属于 cgroup A,在 “内存层级” 中属于 cgroup B)。 层级内的 cgroup 是树状继承关系:子 cgroup 会继承父 cgroup 的资源配置(可覆盖),便于批量管理(如 “Web 服务” 父组下的 “API 服务” 子组继承 CPU 权重)。 ```bash root@ubuntu:~# grep cgroup /proc/mounts | awk -F " " '{print $2 "=" $4}' /sys/fs/cgroup=rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot ``` > 主要的子系统 cgroups 包含多个子系统,分别对应不同的资源类型,以下是最常用的子系统及其功能: | 子系统 | 作用说明 | 核心配置参数示例 | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | cpu | 限制进程组的 CPU 时间使用(支持相对权重和绝对限制) | - cpu.shares:CPU 相对权重(如 1024,值越高优先级越高)<br />- cpu.cfs_quota_us:CPU 绝对限制(如 50000 表示最多使用 50% 核心) | | cpuacct | 统计进程组的 CPU 使用量(用户态、内核态耗时) | - cpuacct.usage:总 CPU 耗时(纳秒)<br />- cpuacct.stat:用户态 / 内核态耗时统计 | | memory | 限制进程组的内存使用(物理内存、Swap、内核内存),并统计使用量 | - memory.limit_in_bytes:物理内存上限(如 512M)<br />- memory.memsw.limit_in_bytes:物理内存 + Swap 总上限<br />- memory.usage_in_bytes:当前内存使用量 | | blkio | 限制进程组对块设备(磁盘)的 IO 速率,控制 IO 优先级 | - blkio.throttle.read_bps_device:读速率限制(如 8:0 10485760 表示对 8:0 设备限制读 10MB/s)<br />- blkio.weight:IO 相对权重 | | devices | 控制进程组对设备(如 /dev/sda)的访问权限(读 / 写 / 创建) | - devices.allow:允许访问的设备(如 b 8:0 rw 允许读写 8:0 块设备)<br />- devices.deny:禁止访问的设备 | | pids | 限制进程组可创建的最大进程数,防止 “进程爆炸” | - pids.max:最大进程数(如 100,超过则无法创建新进程)<br />- pids.current:当前进程数 | | net_cls | 为进程组的网络数据包打上类别标记(classid),配合 tc(流量控制)工具限流 | - net_cls.classid:标记值(如 0x100001),用于 tc 规则匹配 | | net_prio | 控制进程组的网络发送优先级(针对不同网络接口) | - net_prio.prio:默认优先级(0-6)<br />- net_prio.ifpriomap:按接口设置优先级 | | hugetlb | 限制进程组对大页内存(HugeTLB)的使用量(适用于高性能计算场景) | - hugetlb.1GB.limit_in_bytes:1GB 大页的使用上限 | ## 联合文件  ### 概述 联合文件系统(Union File System,简称 UnionFS)是一种**特殊的文件系统技术**,其核心能力是将多个独立的目录(称为 “层” 或 “分支”)的内容**逻辑合并为一个统一的文件系统视图**,同时保持各层的独立性(只读层不可修改,可写层单独记录变更)。 联合文件系统的本质是 “逻辑合并多个目录,物理保持分层”: - 从用户视角看,合并后的文件系统是一个单一的目录树,包含所有底层目录的文件和目录; - 从存储视角看,各底层目录(层)仍独立存在,仅在访问时被 “联合” 展示,修改操作仅作用于最上层的可写层,不影响底层只读层。 > 目标 资源复用:多个场景共享底层只读数据(如容器共享基础镜像层),避免重复存储; 轻量修改:对合并视图的修改仅记录在可写层,无需复制整个底层数据; 环境隔离:不同场景的修改相互独立(如不同容器的变更存储在各自的可写层)。 ### 特性 联合文件系统的特性围绕 “分层” 和 “合并” 展开。 > 分层结构(Layers) 联合文件系统由**多个 “层”** 组成,每层对应一个实际的目录(或文件系统)。 层分为**只读层(Read-Only Layer)** 和**可写层(Read-Write Layer)**: - 只读层:通常包含基础数据(如操作系统文件、应用依赖),不可修改,可被多个场景共享; - 可写层:位于最上层,用于记录用户的修改操作(新建、删除、修改文件),仅对当前场景可见。 > 写时复制(Copy-on-Write, CoW) 这是联合文件系统实现 “轻量修改” 的核心机制: 当读取文件时,系统会从底层只读层依次查找,找到后直接返回内容(共享底层数据); 当修改(写、删、改)一个文件时: 1. 若文件来自只读层,系统会先将该文件**复制到可写层**; 2. 所有修改仅在可写层的副本上进行,**原只读层的文件保持不变**; 优势:避免修改时复制整个只读层,仅复制被修改的单个文件,极大节省磁盘空间和时间。 > 覆盖删除 当删除联合视图中的一个文件时(该文件来自只读层),系统不会真正删除只读层的文件,而是通过 “掩盖删除” 机制标记该文件为 “已删除”: - 在可写层创建一个特殊的 “whiteout” 文件(如 .wh.<文件名>),标识该文件在联合视图中已被删除; - 后续访问时,系统会优先识别可写层的 whiteout 文件,屏蔽底层只读层的原文件,从视图上表现为 “已删除”。 > 联合挂载(union mount) 通过 “联合挂载” 将多个层的目录合并为一个统一的挂载点,用户通过该挂载点访问所有层的内容: 例如:将 layer1/(只读)、layer2/(只读)、layer3/(可写)联合挂载到 union/,则 union/ 中会显示 layer1、layer2、layer3 的所有文件,且修改仅保存在 layer3。 ### 原理 假设联合文件系统由 3 层组成:base/(只读,基础系统文件)、app/(只读,应用依赖)、write/(可写,用户修改),联合挂载到 union/。 > 1、读文件操作 当访问 union/etc/hosts 时,系统会按层的优先级(通常从上到下,或配置的顺序)依次查找: - 若 write/etc/hosts 存在,直接返回; - 若不存在,查找 app/etc/hosts;若仍不存在,查找 base/etc/hosts,找到后返回。 > 2、修改文件操作 当修改 union/etc/hosts 时(假设该文件仅存在于 base/etc/hosts): 1. 触发写时复制(CoW):系统将 base/etc/hosts 复制到 write/etc/hosts; 2. 修改操作仅作用于 write/etc/hosts,base/etc/hosts 保持不变; 3. 后续访问 union/etc/hosts 时,系统优先返回 write/ 中的修改后版本。 > 3、删除文件操作 当删除 union/usr/bin/oldtool 时(该文件存在于 app/usr/bin/oldtool): 1. 系统不在 app/ 中删除文件,而是在 write/usr/bin/ 中创建 whiteout 文件 .wh.oldtool; 2. 后续访问 union/usr/bin/oldtool 时,系统识别到 .wh.oldtool,判定文件已删除,返回 “不存在”。 > 4、新建文件操作 当在 union/tmp/newfile 中新建文件时,文件直接被创建在可写层 write/tmp/newfile,不影响底层只读层。 ### 实现方案 联合文件系统有多种实现(不同内核或工具支持),核心逻辑一致,但在性能、兼容性、功能细节上有差异。以下是最常用的几种: > overlay/overlay2(主流容器选择) 特点:Linux 内核原生支持(3.18+ 支持 overlay,4.0+ 推荐 overlay2),架构简单(仅需 “lowerdir” 只读层、“upperdir” 可写层、“workdir” 临时工作层),性能优异。 应用:Docker 默认推荐的存储驱动(替代早期的 AUFS),Kubernetes 容器也广泛使用。 优势:对小文件操作效率高,Copy-on-Write 开销低,内核支持成熟。 > AUFS(Advanced Multi-Layered Unification Filesystem) 特点:最早被 Docker 采用的联合文件系统,支持多层只读层(最多 127 层),但非 Linux 内核原生(需额外补丁)。 局限:性能在多层场景下较差,内核维护成本高,逐渐被 overlay2 取代。 > devicemapper 特点:基于块设备的快照机制实现分层(而非文件级),通过 “thin provisioning”(瘦分配)支持动态空间分配。 应用:早期 Docker 在 CentOS/RHEL 上的默认驱动(因这些系统内核默认不支持 AUFS)。 局限:文件级操作性能较差(块设备层操作),空间效率低于 overlay2。 > btrfs/zfs(高级文件系统自带联合功能) 特点:btrfs(Linux)和 zfs(跨平台)是原生支持 “快照” 和 “子卷” 的高级文件系统,可通过快照实现分层存储(类似联合文件系统)。 优势:支持 Copy-on-Write 块级操作,性能优异,适合大规模存储场景。 应用:部分容器平台(如 Docker)支持将其作为存储驱动,尤其在需要高效快照的场景。 ## Overlay ### 概述 Docker 的存储驱动(Storage Driver)是负责管理容器镜像分层存储、实现写时复制(Copy-on-Write, CoW)及容器可写层的核心组件。 目前,Docker 在绝大多数现代 Linux 发行版上默认推荐并优先使用 overlay2 存储驱动(自 Docker 17.06 起成为默认选择),其基于 Linux 内核的 overlay 文件系统改进而来,兼具性能、兼容性和资源效率优势。 > 适用场景 overlay2 是一种联合文件系统(UnionFS)实现,专为容器场景设计,核心目标是: - 高效管理镜像的多层只读结构(复用底层镜像层,减少冗余存储); - 通过写时复制机制实现容器可写层与镜像层的隔离(容器修改不影响镜像); - 提供优于其他驱动的 I/O 性能和资源利用率,适配大规模容器部署。 ### 工作原理 overlay2 通过多层目录的联合挂载实现镜像与容器的文件系统管理,核心结构包括 4 个关键目录。 > 核心目录组成 lowerdir(只读镜像层):由容器依赖的所有镜像层组成,按层级顺序排列(底层在前,上层在后)。 - ```txt 例如,一个 Nginx 容器的 lowerdir 可能包含: /var/lib/docker/overlay2/[base层ID]/diff(基础系统层)、 /var/lib/docker/overlay2/[依赖层ID]/diff(Nginx 依赖层)、 /var/lib/docker/overlay2/[应用层ID]/diff(Nginx 程序层)。 ``` upperdir(容器可写层):容器启动时创建的唯一可写层,用于存储容器内的所有修改(新建、删除、修改文件)。 - ```txt 路径通常为 /var/lib/docker/overlay2/[容器层ID]/diff ``` merged(联合视图):容器内看到的统一文件系统视图,是 lowerdir(只读镜像层)和 upperdir(可写层)的联合挂载点,容器进程通过该目录访问所有文件。 - ```txt 路径通常为 /var/lib/docker/overlay2/[容器层ID]/merged ``` workdir(工作目录):overlay2 用于临时操作(如写时复制过程中的文件暂存)的目录,必须与 upperdir 在同一文件系统。 - ```txt 路径通常为 /var/lib/docker/overlay2/[容器层ID]/work ```  ### 核心机制 overlay2 的高效性源于对联合文件系统核心机制的优化实现。 > 写时复制(CoW): 当容器修改一个来自 lowerdir(镜像层)的文件时: 1. 系统先检查 upperdir 中是否已有该文件的副本,若有则直接修改; 2. 若没有,将 lowerdir 中的文件**复制到 upperdir**(仅复制单个文件,而非整个层); 3. 修改操作仅作用于 upperdir 中的副本,lowerdir 中的原文件保持不变(确保镜像层可被其他容器复用)。 例:容器修改 /etc/hosts(来自基础镜像层),overlay2 会将 lowerdir 中的 /etc/hosts 复制到 upperdir/etc/hosts,修改仅发生在 upperdir。 > 掩盖删除(Whiteout): 当容器删除一个来自 lowerdir 的文件时: 1. 不直接删除 lowerdir 中的文件(保护镜像层); 2. 在 upperdir 中创建一个特殊的 “whiteout 文件”(命名格式为 .wh.<文件名>),标识该文件在联合视图中已被删除; 3. 容器访问该文件时,overlay2 会优先识别 upperdir 中的 whiteout 文件,返回 “文件不存在”。 例:容器删除 /usr/bin/oldtool(来自镜像层),overlay2 会在 upperdir/usr/bin/ 中创建 .wh.oldtool,容器中再访问 /usr/bin/oldtool 时会显示已删除。
毛林
2025年10月21日 20:12
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码