Docker镜像分层与存储优化:从overlay2到多阶段构建的完整实践指南

发布时间:2026/10/14 18:53:19
Docker镜像分层与存储优化:从overlay2到多阶段构建的完整实践指南 Docker 运行时机制我上一篇已经聊过重点讲了容器进程怎么被启动、命名空间和 cgroups 怎么配合。这一篇标题是“docker-image-layer-storage-optimization”核心就一件事把 Docker 镜像分层存储彻底讲透并且从构建、运行到维护给出真正能落地的存储优化方案。如果你被镜像体积困扰过、磁盘空间莫名其妙告警或者对 overlay2 到底是什么一知半解这篇就是写给你的。1. 把镜像分层这件事彻底讲明白1.1 镜像是一叠只读层不是一个大文件夹我刚接触 Docker 时也以为镜像就像虚拟机镜像一样是一整个大文件。后来才发现完全不是这么回事。Docker 镜像采用内容寻址存储可以拆成多个只读层每一层只记录和上一层之间的差异并用 SHA-256 摘要作为唯一标识。镜像不是一次性生成的完整 rootfs而是 Dockerfile 里的指令逐条执行后一层层叠加出来的结果。举个具体例子Dockerfile 里写 RUN apt-get install 某个软件执行后就会产生新的一层。这一层记录的是从“当前状态”到“安装完成状态”的全部文件系统变化新增了哪些文件、修改了哪些文件、删除了哪些文件。只要某一层的内容完全不变它的哈希值就不会变多个镜像就可以安全共享同一批底层。这也是为什么所有镜像都基于同一个基础镜像时本机磁盘占用并不会按镜像数量线性增长而是大量复用底层数据。想直观看到分层结构最常用的命令是 docker history。比如 docker history nginx:alpine会按构建顺序列出每一层对应 Dockerfile 中的指令同时给出 SIZE 和 COMMENT。很多人看到 missing 字样会困惑其实那只是表示这一层是从父镜像继承来的在当前机器上没有对应的构建上下文。这个命令是我排查镜像体积问题时第一优先使用的工具简单直接。1.2 写时复制容器改动为什么不会破坏镜像镜像层是只读的那容器怎么写入文件呢答案是存储驱动在镜像层之上叠加了一个容器可写层。启动容器时Docker 会把所有镜像只读层和这个可写层联合挂载成一个完整视图对容器进程来说它就是普通的根文件系统。写入动作触发的是写时复制机制。容器要修改镜像层里的某个文件时存储驱动会先把文件从只读层复制到容器可写层再在副本上修改原来的只读层保持原样不动。删除文件也不是真的删除只读层中的文件而是写入一个 whiteout 标记在合并视图里把这个文件“遮住”让上层不再看到它。如果你在容器里删掉 /etc/nginx/nginx.conf再从宿主机看容器可写层的 diff会发现那层的处理逻辑不是直接移除文件而是建立特殊标记。这套设计价值巨大。同一台机器跑几十个相同镜像的容器底层只读层完全共享每个容器只有自己的小可写层独立变化。打个比方镜像层像一份共享的教材底稿每个人把批注和笔记写在自己的透明便利贴上互不影响也不改动底稿。生产环境里很多容器共用镜像而不爆炸靠的就是这套机制。1.3 镜像元数据和分层的关系除了文件系统层Docker 镜像还有两份关键元数据config 文件记录容器配置、环境变量、默认命令和历史指令等信息manifest 列出所有层及其对应摘要。docker image inspect 可以查看完整内容其中 GraphDriver 字段会显示当前镜像在本地存储驱动下的分层数据。有个容易混淆的点镜像层的本地 ID比如 overlay2 目录下那串哈希和内容寻址的 diffID 不是一回事。前者是存储引擎在本地实现层引用的哈希后者是未压缩文件内容的 SHA-256两者通过 chainID 关联。实际排障时通常不用深挖到这一层但理解它们不同能避免你对比 docker inspect 输出时产生困惑。当你看到 /var/lib/docker/overlay2 下有一堆长哈希目录时要知道这些只是存储驱动的具体布局不完全是镜像 layer 的直接映射。2. 存储驱动选型与调优overlay2 是默认答案吗2.1 overlay2目前最主流也最值得优先选存储驱动负责把镜像层展开并合并成可写视图。目前 Linux 上绝大多数场景都该用 overlay2它基于内核的 overlayfs把只读层作为 lowerdir容器可写层作为 upperdir最后挂载成一个 merged 视图。overlay2 有一个关键优势它会尝试把镜像层文件通过硬链接方式共享到底层数据而不是复制。假设两个镜像共享同一个基础镜像层overlay2 可以用硬链接把相同文件关联到同一 inode明显减少磁盘占用。这也是为什么 /var/lib/docker/overlay2 目录里有很多链接数大于 1 的文件。容器运行时lowerdir 和 upperdir 的合并由内核完成性能远好于用户态存储驱动。不过选 overlay2 有前提条件内核支持 overlayfs 一般没问题底层文件系统必须是 xfs 且开启 ftype1或者 ext4。如果 xfs 没开 ftypeDocker 可能拒绝使用 overlay2报错信息里会提到 d_type。我记得有次在一台老机器的旧分区上装 Docker无论如何都无法用 overlay2最后检查分区格式才发现不支持属于环境没打底。排查路径很简单先 /proc/filesystems 看有没有 overlay再 df -T 看分区类型。2.2 rootless 模式下的 fuse-overlayfs 与 vfs 兜底rootless 模式下没有 root 权限普通用户无法挂载内核 overlayfs这时通常会落到 fuse-overlayfs 或 vfs。fuse-overlayfs 通过 FUSE 用户态文件系统实现 overlay 语义功能基本兼容性能虽然比内核态差一些但正常跑绝大多数容器没有问题。如果环境里没有 fuse-overlayfsDocker 可能会退回 vfs。vfs 不做写时复制而是为每个容器完整复制一份镜像文件空间占用巨大性能也差。我的评价是能不用就不用生产环境一旦落到 vfs磁盘很快会被撑爆。怎么确认当前用的哪个驱动docker info 里看 Storage Driver 一行就行如果显示 vfs基本可以断定配置有问题。在 daemon.json 里显式配置 storage-driver: fuse-overlayfs配合 rootless 使用可以避免踩到自动探测的坑。如果你只是在自己笔记本上跑 rootless Docker 做开发验证fuse-overlayfs 完全够用不必强求内核 overlay2。2.3 与存储驱动相关的几个关键参数daemon 的 /etc/docker/daemon.json 集中存放存储相关配置。常见参数有 storage-driver、data-root、storage-opts。设置>

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询