mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1929 字
5 分钟
为什么 Docker 使用分层镜像
2024-03-13

Docker 镜像设计是容器技术的核心创新之一。一个 Ubuntu 基础镜像约 70MB,而在其上安装 Nginx 后,最终镜像可能只增加几 MB。这种”增量存储”的背后,是 Docker 的分层镜像设计——通过 UnionFS(联合文件系统)实现的多层叠加机制。为什么 Docker 选择这种设计?答案藏在存储效率、构建速度和分发优化三个维度的极致考量中。

一、Docker 镜像的存储困境#

1.1 传统虚拟机镜像的问题#

在 Docker 出现之前,虚拟机镜像是主流的应用打包方式:

flowchart TB subgraph 虚拟机镜像 VM1[VM 镜像 A<br/>Ubuntu + App1<br/>10 GB] VM2[VM 镜像 B<br/>Ubuntu + App2<br/>10 GB] VM3[VM 镜像 C<br/>Ubuntu + App3<br/>10 GB] end Note over VM1,VM3: 三个镜像共 30 GB<br/>大量重复的 Ubuntu 系统

传统虚拟机镜像的问题:

问题表现影响
存储冗余每个镜像包含完整操作系统磁盘空间浪费严重
分发效率低传输完整镜像文件网络带宽消耗大
构建速度慢从头创建完整镜像部署周期长
更新困难修改需要重建整个镜像运维成本高

1.2 Docker 镜像的设计目标#

Docker 需要解决的核心问题:

# 传统方式的存储开销
base_image_size = 700 # MB, Ubuntu 基础镜像
app_size = 50 # MB, 应用程序
# 10 个基于同一基础镜像的应用
traditional_storage = 10 * (base_image_size + app_size)
print(f"传统方式存储:{traditional_storage} MB")
# Docker 分层方式
docker_storage = base_image_size + 10 * app_size
print(f"Docker 分层存储:{docker_storage} MB")
print(f"节省空间:{(1 - docker_storage/traditional_storage)*100:.1f}%")
# 输出:
# 传统方式存储:7500 MB
# Docker 分层存储:1200 MB
# 节省空间:84.0%

1.3 分层设计的核心理念#

Docker 镜像采用”分层叠加”的设计理念:

flowchart LR subgraph 分层镜像 L1[基础层 Ubuntu<br/>只读] L2[依赖层<br/>只读] L3[应用层<br/>只读] L4[容器层<br/>可写] end L1 --> L2 --> L3 --> L4 Note over L1,L4: 每层独立存在<br/>按需组合叠加

二、UnionFS:联合文件系统原理#

2.1 什么是 UnionFS#

UnionFS(Union File System)是一种将多个目录”联合挂载”到同一挂载点的文件系统技术:

flowchart TB subgraph 联合挂载视图 V["/merged<br/>联合视图"] end subgraph 底层目录 A["/dirA<br/>file1.txt<br/>file2.txt"] B["/dirB<br/>file2.txt<br/>file3.txt"] end A --> V B --> V Note over V: file1.txt 来自 dirA<br/>file2.txt 优先使用上层<br/>file3.txt 来自 dirB

UnionFS 的核心特性:

特性说明
分支(Branch)每个底层目录称为一个分支
优先级上层分支的文件优先级高于下层
只读/可写分支可以设置为只读或可写
白标记标记下层文件被删除,实现”删除”效果
联合视图用户看到的是所有分支合并后的统一视图

2.2 UnionFS 的工作原理#

当读取文件时,UnionFS 从上层到下层依次查找:

sequenceDiagram participant App as 应用程序 participant Union as UnionFS participant U as 上层目录 participant L as 下层目录 App->>Union: 读取 /merged/file.txt Union->>U: 查找 file.txt alt 文件在上层存在 U-->>Union: 返回文件内容 else 文件在上层不存在 Union->>L: 查找 file.txt L-->>Union: 返回文件内容 end Union-->>App: 返回文件内容

2.3 UnionFS 的多种实现#

Linux 上有多种 UnionFS 实现:

timeline title 联合文件系统演进历史 2004 : UnionFS : 最早的联合文件系统 2006 : AUFS : UnionFS 的改进版 2010 : OverlayFS : 合并到 Linux 主线 2014 : OverlayFS v2 : 支持多层叠加
实现特点使用场景
UnionFS最早的实现,功能基础已逐渐淘汰
AUFS支持多层,曾被 Docker 默认使用早期 Docker 版本
OverlayFS主线内核支持,性能优秀现代 Docker 默认
Btrfs原生支持快照和子卷特定存储驱动
ZFS企业级存储方案高可靠性场景

三、OverlayFS:Docker 的默认存储驱动#

3.1 OverlayFS 的核心概念#

OverlayFS 是目前 Docker 默认使用的存储驱动,其结构简洁高效:

flowchart TB subgraph OverlayFS 结构 M["merged<br/>合并视图"] U["upperdir<br/>上层(可写)"] L1["lowerdir 1<br/>下层(只读)"] L2["lowerdir 2<br/>下层(只读)"] W["workdir<br/>工作目录"] end U --> M L1 --> M L2 --> M W -.-> U Note over M: 用户看到的最终视图<br/>Note over U: 容器写入层<br/>Note over L1,L2: 镜像只读层

OverlayFS 的三个关键目录:

目录作用特性
lowerdir镜像的只读层只读
upperdir容器的可写层可写
merged合并后的统一视图可读写
workdirOverlayFS 内部使用必需

3.2 OverlayFS 的文件查找过程#

当容器读取文件时:

flowchart TD A[读取文件请求] --> B{upperdir 中存在?} B -->|是| C[返回 upperdir 文件] B -->|否| D{lowerdir 中存在?} D -->|是| E[返回 lowerdir 文件] D -->|否| F[返回 ENOENT 错误] style A fill:#e1f5fe style C fill:#c8e6c9 style E fill:#c8e6c9 style F fill:#ffcdd2

3.3 OverlayFS 的实际挂载示例#

# 创建目录结构
mkdir -p /tmp/overlay/{lower1,lower2,upper,work,merged}
# 在下层目录创建测试文件
echo "Layer 1 content" > /tmp/overlay/lower1/file1.txt
echo "Layer 2 content" > /tmp/overlay/lower2/file2.txt
# 挂载 OverlayFS
mount -t overlay overlay \
-o lowerdir=/tmp/overlay/lower2:/tmp/overlay/lower1 \
-o upperdir=/tmp/overlay/upper \
-o workdir=/tmp/overlay/work \
/tmp/overlay/merged
# 查看合并视图
ls /tmp/overlay/merged/
# 输出: file1.txt file2.txt

3.4 OverlayFS vs Overlay2#

Docker 支持两种 OverlayFS 驱动:

flowchart LR subgraph overlay O1[镜像层] --> O2[init 层] O2 --> O3[容器层] end subgraph overlay2 N1[Layer 1] --> N2[Layer 2] N2 --> N3[Layer 3] N3 --> N4[容器层] end Note over O1,O3: overlay 最多两层<br/>性能较差 Note over N1,N4: overlay2 支持多层<br/>性能优秀
特性overlayoverlay2
最大层数限制为 2 层支持多达 128 层
性能需要硬链接原生多层支持
磁盘消耗较大(硬链接)较小
推荐程度已弃用推荐(Docker 默认)

四、Copy-on-Write 机制详解#

4.1 什么是 Copy-on-Write#

Copy-on-Write(写时复制)是 Docker 分层镜像的核心机制:

sequenceDiagram participant C as 容器进程 participant U as upperdir participant L as lowerdir Note over C,L: 读取文件(不复制) C->>L: 读取 /etc/config.conf L-->>C: 返回文件内容 Note over C,L: 修改文件(写时复制) C->>U: 写入 /etc/config.conf U->>L: 复制文件到 upperdir U->>U: 修改副本 U-->>C: 写入完成 Note over U: 后续读取直接使用 upperdir 副本

4.2 CoW 的详细流程#

当容器尝试修改只读层的文件时:

flowchart TD A[容器请求修改文件] --> B{文件在 upperdir?} B -->|是| C[直接修改 upperdir 文件] B -->|否| D{文件在 lowerdir?} D -->|是| E[复制文件到 upperdir] E --> F[修改 upperdir 副本] D -->|否| G[在 upperdir 创建新文件] C --> H[完成修改] F --> H G --> H style A fill:#e3f2fd style E fill:#fff3e0 style H fill:#e8f5e9

4.3 CoW 的存储开销计算#

# Copy-on-Write 的存储效率分析
base_layer_size = 700 # MB, Ubuntu 基础镜像
modified_files_size = 10 # MB, 实际修改的文件
# 传统方式:需要复制整个镜像
traditional_size = base_layer_size + modified_files_size
print(f"传统方式存储:{traditional_size} MB")
# CoW 方式:只存储修改的部分
cow_size = modified_files_size # 只存储修改的文件
print(f"CoW 方式存储:{cow_size} MB")
# 如果启动 100 个相同容器
print(f"\n100 个容器的存储开销:")
print(f"传统方式:{100 * traditional_size} MB")
print(f"CoW 方式:{base_layer_size + 100 * cow_size} MB")
# 输出:
# 传统方式存储:710 MB
# CoW 方式存储:10 MB
#
# 100 个容器的存储开销:
# 传统方式:71000 MB
# CoW 方式:1700 MB

4.4 CoW 的性能影响#

Copy-on-Write 的性能特点:

操作性能影响原因
读取文件无额外开销直接读取,无需复制
创建文件无额外开销直接写入 upperdir
修改文件首次有复制开销需要从 lowerdir 复制
删除文件创建白标记不实际删除,只标记删除
xychart-beta title "文件操作性能对比(相对值)" x-axis ["读取", "创建", "首次修改", "再次修改", "删除"] y-axis "相对耗时" 0 --> 10 bar [1, 1, 5, 1, 1]

4.5 白标记(Whiteout)机制#

当容器删除文件时,OverlayFS 使用白标记实现”删除”效果:

flowchart LR subgraph 删除前 L1["lowerdir<br/>file.txt"] U1["upperdir<br/>(空)"] M1["merged<br/>file.txt 存在"] end subgraph 删除后 L2["lowerdir<br/>file.txt 仍存在"] U2["upperdir<br/>.wh.file.txt<br/>(白标记)"] M2["merged<br/>file.txt 消失"] end L1 --> U1 --> M1 L2 --> U2 --> M2 Note over U2: 白标记文件名以 .wh. 开头<br/>OverlayFS 会隐藏对应文件

五、分层镜像的三重优势#

5.1 存储效率#

分层设计大幅降低存储开销:

flowchart TB subgraph 共享基础镜像 B[Ubuntu 20.04<br/>72 MB] N[Nginx 层<br/>5 MB] R[Redis 层<br/>3 MB] P[Python 层<br/>15 MB] end B --> N B --> R B --> P Note over N,P: 三个镜像共享基础层<br/>总存储:72 + 5 + 3 + 15 = 95 MB<br/>而非:3 × 72 + 23 = 239 MB

存储效率对比:

# 计算分层存储的效率
base_images = {
"ubuntu": 72,
"alpine": 5,
"debian": 114,
}
applications = {
"nginx": 5,
"redis": 3,
"nodejs": 10,
"python": 15,
}
# 传统方式:每个应用独立镜像
traditional_total = 0
for base, base_size in base_images.items():
for app, app_size in applications.items():
traditional_total += base_size + app_size
# 分层方式:共享基础镜像
layered_total = sum(base_images.values()) + sum(applications.values())
print(f"传统方式总存储:{traditional_total} MB")
print(f"分层方式总存储:{layered_total} MB")
print(f"存储效率提升:{(1 - layered_total/traditional_total)*100:.1f}%")
# 输出:
# 传统方式总存储:636 MB
# 分层方式总存储:224 MB
# 存储效率提升:64.8%

5.2 构建速度#

Dockerfile 的分层构建机制:

flowchart LR subgraph Dockerfile D1["FROM ubuntu:20.04"] D2["RUN apt-get update"] D3["RUN apt-get install nginx"] D4["COPY . /app"] D5["CMD nginx"] end subgraph 镜像层 L1["Layer 1<br/>基础镜像"] L2["Layer 2<br/>apt 更新"] L3["Layer 3<br/>安装 nginx"] L4["Layer 4<br/>应用代码"] end D1 --> L1 D2 --> L2 D3 --> L3 D4 --> L4 Note over L1,L4: 每条指令创建一层<br/>利用缓存加速构建

构建缓存机制:

# Dockerfile 示例
FROM ubuntu:20.04
# 这一层会被缓存
RUN apt-get update && apt-get install -y \
nginx \
curl \
&& rm -rf /var/lib/apt/lists/*
# 这一层也会被缓存(依赖文件不变)
COPY requirements.txt /app/
RUN pip install -r /app/requirements.txt
# 这层每次构建都会更新(代码经常变化)
COPY . /app/
CMD ["python", "/app/main.py"]
flowchart TD A[执行 docker build] --> B{检查缓存} B -->|基础镜像缓存命中| C[使用缓存 Layer 1] B -->|缓存未命中| D[拉取基础镜像] C --> E{apt 命令变化?} E -->|否| F[使用缓存 Layer 2-3] E -->|是| G[重新执行 apt] F --> H{requirements.txt 变化?} H -->|否| I[使用缓存 Layer 4] H -->|是| J[重新安装依赖] I --> K[复制应用代码] J --> K G --> K D --> K style C fill:#c8e6c9 style F fill:#c8e6c9 style I fill:#c8e6c9

5.3 分发优化#

镜像推送和拉取的增量传输:

sequenceDiagram participant D as 开发机 participant R as Registry participant P as 生产机 Note over D,R: 首次推送镜像 D->>R: 推送 ubuntu:20.04 (72 MB) D->>R: 推送 nginx 层 (5 MB) Note over R: 镜像已存储 Note over D,P: 首次拉取镜像 P->>R: 拉取镜像 R->>P: 传输 ubuntu:20.04 (72 MB) R->>P: 传输 nginx 层 (5 MB) Note over D,P: 更新应用(只修改应用层) D->>R: 推送新应用层 (2 MB) Note over R: 基础层不变 P->>R: 拉取更新 R->>P: 基础层已存在,跳过 R->>P: 只传输新应用层 (2 MB)

分发效率计算:

# 镜像分发效率分析
layers = {
"ubuntu": {"size": 72, "modified": False},
"nginx": {"size": 5, "modified": False},
"dependencies": {"size": 20, "modified": False},
"app": {"size": 3, "modified": True}, # 只有应用层变化
}
# 首次拉取:传输所有层
first_pull = sum(layer["size"] for layer in layers.values())
# 更新后拉取:只传输变化的层
update_pull = sum(
layer["size"] for layer in layers.values() if layer["modified"]
)
print(f"首次拉取:{first_pull} MB")
print(f"更新拉取:{update_pull} MB")
print(f"传输节省:{(1 - update_pull/first_pull)*100:.1f}%")
# 输出:
# 首次拉取:100 MB
# 更新拉取:3 MB
# 传输节省:97.0%

六、Docker 镜像与虚拟机镜像对比#

6.1 架构差异#

flowchart TB subgraph Docker 容器 subgraph 容器 1 CA1[App A] end subgraph 容器 2 CA2[App B] end CD[Docker Engine] CH[Host OS] CS[共享镜像层] end subgraph 虚拟机 subgraph VM 1 VMA1[App A] VMO1[Guest OS] end subgraph VM 2 VMA2[App B] VMO2[Guest OS] end VH[Hypervisor] VHO[Host OS] end style CS fill:#e8f5e9 style VMO1 fill:#ffcdd2 style VMO2 fill:#ffcdd2

6.2 存储模型对比#

维度Docker 镜像虚拟机镜像
基础镜像多容器共享每个虚拟机独立
存储格式分层叠加(UnionFS)完整磁盘镜像
增量更新只传输变化的层需要传输完整镜像
启动速度秒级分钟级
存储效率高(去重)低(重复存储)
隔离程度进程级硬件级

6.3 镜像大小对比#

xychart-beta title "镜像大小对比(MB)" x-axis ["Ubuntu", "Nginx", "Redis", "Python", "Node.js"] y-axis "大小(MB)" 0 --> 1000 bar [72, 77, 75, 87, 82] bar [500, 505, 503, 513, 508]
# 镜像大小对比
workloads = ["Ubuntu", "Nginx", "Redis", "Python", "Node.js"]
docker_sizes = [72, 77, 75, 87, 82] # MB
vm_sizes = [500, 505, 503, 513, 508] # MB, 包含完整 Guest OS
for i, workload in enumerate(workloads):
reduction = (1 - docker_sizes[i]/vm_sizes[i]) * 100
print(f"{workload}: Docker {docker_sizes[i]}MB vs VM {vm_sizes[i]}MB, 节省 {reduction:.1f}%")
# 输出:
# Ubuntu: Docker 72MB vs VM 500MB, 节省 85.6%
# Nginx: Docker 77MB vs VM 505MB, 节省 84.8%
# Redis: Docker 75MB vs VM 503MB, 节省 85.1%
# Python: Docker 87MB vs VM 513MB, 节省 83.0%
# Node.js: Docker 82MB vs VM 508MB, 节省 83.9%

6.4 性能对比#

操作Docker 容器虚拟机原因
启动时间0.1-2 秒30-120 秒无需启动操作系统
内存占用MB 级GB 级共享宿主机内核
CPU 开销接近原生5-10% 虚拟化开销无需硬件虚拟化
I/O 性能接近原生10-20% 开销直接访问宿主机文件系统

七、镜像层的实际分析#

7.1 查看镜像分层#

使用 docker history 命令分析镜像层:

# 拉取镜像
docker pull nginx:latest
# 查看镜像层
docker history nginx:latest
# 输出示例:
# IMAGE CREATED CREATED BY SIZE
# 605c77e624dd 2 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
# <missing> 2 weeks ago /bin/sh -c #(nop) EXPOSE 80 0B
# <missing> 2 weeks ago /bin/sh -c #(nop) COPY file:09a214a3e07c976… 4.62kB
# <missing> 2 weeks ago /bin/sh -c apt-get update && apt-get install… 61.1MB
# <missing> 2 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
# <missing> 2 weeks ago /bin/sh -c #(nop) ADD file:4060ec96569404d… 138MB

7.2 镜像层的关系图#

flowchart BT subgraph nginx:latest 镜像 L1["Layer 0<br/>Debian 基础镜像<br/>138 MB"] L2["Layer 1<br/>安装依赖<br/>61 MB"] L3["Layer 2<br/>配置文件<br/>4.6 KB"] L4["Layer 3<br/>暴露端口<br/>0 B"] L5["Layer 4<br/>启动命令<br/>0 B"] end subgraph 运行中的容器 C["容器层<br/>可写"] end L1 --> L2 --> L3 --> L4 --> L5 --> C Note over L1,L5: 只读镜像层<br/>Note over C: 容器启动时创建<br/>存储所有修改

7.3 存储驱动查看#

# 查看 Docker 存储驱动
docker info | grep "Storage Driver"
# 输出:
# Storage Driver: overlay2
# 查看 OverlayFS 挂载信息
mount | grep overlay
# 输出示例:
# overlay on /var/lib/docker/overlay2/.../merged
# type overlay (rw,relatime,
# lowerdir=/var/lib/docker/overlay2/l/XXX:/var/lib/docker/overlay2/l/YYY,
# upperdir=/var/lib/docker/overlay2/.../diff,
# workdir=/var/lib/docker/overlay2/.../work)

7.4 层的物理存储位置#

flowchart TB subgraph "/var/lib/docker/overlay2" L["l/<br/>符号链接目录"] D1["<id>/diff<br/>upperdir"] D2["<id>/diff<br/>lowerdir"] W["<id>/work<br/>workdir"] M["<id>/merged<br/>挂载点"] end subgraph "镜像元数据" IM["/var/lib/docker/image/overlay2<br/>layerdb/"] end L --> D1 L --> D2 D1 --> M D2 --> M W -.-> M

八、最佳实践建议#

8.1 优化 Dockerfile 以减少层数#

# 不推荐:每条 RUN 创建一层
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get install -y curl
RUN apt-get clean
# 推荐:合并相关命令
RUN apt-get update && apt-get install -y \
nginx \
curl \
&& rm -rf /var/lib/apt/lists/*

8.2 利用构建缓存#

# 推荐:将变化最少的部分放在前面
FROM node:18-alpine
# 安装依赖(变化少)
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 复制代码(变化多)
COPY . .
CMD ["node", "server.js"]
flowchart LR subgraph "优化的 Dockerfile 层" A["Layer 1: 基础镜像<br/>几乎不变"] B["Layer 2: 依赖<br/>偶尔变化"] C["Layer 3: 代码<br/>频繁变化"] end A --> B --> C Note over A: 高缓存命中率 Note over B: 中缓存命中率 Note over C: 低缓存命中率

8.3 使用多阶段构建#

# 构建阶段
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o myapp
# 运行阶段
FROM alpine:latest
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]

多阶段构建的优势:

flowchart TB subgraph "传统构建" T1["Go 编译器 1.5 GB"] T2["源代码"] T3["依赖包"] T4["编译产物 10 MB"] T5["最终镜像<br/>~1.5 GB"] end subgraph "多阶段构建" M1["构建阶段<br/>Go 编译器等"] M2["运行阶段<br/>Alpine + 产物"] M3["最终镜像<br/>~15 MB"] end T1 --> T5 T2 --> T5 T3 --> T5 T4 --> T5 M1 -->|只复制产物| M2 --> M3 style T5 fill:#ffcdd2 style M3 fill:#c8e6c9

8.4 选择合适的基础镜像#

基础镜像大小特点适用场景
ubuntu72 MB完整工具链开发环境
debian80 MB精简版生产环境
alpine5 MB极小,musl libc安全敏感场景
scratch0 MB空镜像静态编译程序
distroless/base20 MB无 shell,安全最小化攻击面
# 基础镜像选择建议
def select_base_image(needs):
if needs.get("static_binary"):
return "scratch"
elif needs.get("minimal_size"):
return "alpine"
elif needs.get("security_critical"):
return "distroless/base"
elif needs.get("development"):
return "ubuntu"
else:
return "debian:slim"

8.5 避免存储敏感信息#

# 危险:密码会被永久保存在镜像层中
ENV DATABASE_PASSWORD=secret123
# 推荐:使用运行时挂载或环境变量
# docker run -e DATABASE_PASSWORD=secret123 myapp

九、分层设计的权衡#

9.1 优势总结#

mindmap root((分层镜像优势)) 存储效率 共享基础镜像 去重存储 CoW 机制 构建速度 层级缓存 增量构建 并行构建 分发优化 增量传输 Registry 缓存 P2P 分发 版本管理 镜像标签 层级回滚 历史追溯

9.2 局限性#

局限说明缓解措施
跨平台兼容性镜像与宿主机架构绑定多架构镜像
Windows 容器差异Windows 使用不同的存储驱动平台特定镜像
层数限制Overlay2 最多 128 层合并 RUN 指令
I/O 性能开销OverlayFS 有一定开销使用卷存储数据
镜像碎片频繁构建可能产生无用层定期清理

9.3 适用场景分析#

场景分层镜像推荐度原因
微服务部署存储和分发效率最大化
CI/CD 流水线构建缓存加速迭代
开发环境快速启动和销毁
有状态服务数据需使用卷存储
高性能计算I/O 开销可能有影响

十、总结#

Docker 分层镜像设计是容器技术的核心创新,其价值体现在三个维度:

flowchart TB subgraph 分层设计的核心价值 S[存储效率] B[构建速度] D[分发优化] end S --> S1[共享基础镜像] S --> S2[CoW 机制] S --> S3[去重存储] B --> B1[层级缓存] B --> B2[增量构建] B --> B3[多阶段构建] D --> D1[增量传输] D --> D2[Registry 缓存] D --> D3[按需拉取] style S fill:#e3f2fd style B fill:#e8f5e9 style D fill:#fff3e0

10.1 核心技术要点#

技术作用关键价值
UnionFS联合多个目录为统一视图实现分层叠加
OverlayFSLinux 主线联合文件系统高效的存储驱动
Copy-on-Write写时复制机制存储空间最小化
Whiteout白标记删除只读层的”删除”支持
层级缓存Dockerfile 指令级缓存构建速度提升

Docker 分层设计告诉我们一个重要的系统设计原则:通过合理的抽象和分层,可以在不影响灵活性的前提下,实现资源的高效利用。这种设计思想不仅适用于容器镜像,也对软件架构设计有启发意义。

参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

为什么 Docker 使用分层镜像
https://blog.souloss.com/posts/why-the-design/why-docker-uses-layered-images/
作者
Souloss
发布于
2024-03-13
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时