跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

Docker镜像分层结构与UnionFS原理剖析

Docker镜像由按序堆叠的只读层组成,每层为构建指令产生的增量快照,依赖UnionFS(如overlay2)实现多层合并与写时复制;容器运行时 atop 可写层,共享基础层以节省空间。

Docker镜像不是单个大文件,而是一组按顺序堆叠的只读层(layers),每一层代表一次构建操作的变更。这种分层结构依赖底层存储驱动(如overlay2)提供的联合文件系统(UnionFS)能力,实现高效复用、快速启动和空间节省。

镜像层的本质:只读增量快照每次docker build中的指令(如 RUN、COPY、ADD)都会生成一个新层,该层仅保存与上一层相比的文件增删改差异(diff)。基础镜像(如 ubuntu:22.04)本身也由多个层构成,最底层通常是操作系统根文件系统的精简副本。

所有镜像层默认只读,运行容器时才在顶部叠加一个可写层(container layer)

同一基础镜像的不同衍生镜像(如 python:3.11 和 node:18)会共享底层共用层,降低磁盘占用docker history 可查看每层对应的构建指令、大小及创建时间UnionFS如何“合并”多层目录视图UnionFS(如 overlay2)将多个目录“叠加”成一个统一的挂载点。Docker 启动容器时,它把镜像各只读层 + 一个空的可写层,按顺序合并为一个逻辑文件系统。访问文件时,系统从上到下查找——可写层优先,未命中则向下穿透,直到找到或确认不存在。

写入新文件 → 落入可写层(copy-on-write)

修改已有文件 → 先从只读层复制到可写层再编辑(copy-on-write)

删除文件 → 在可写层放置一个“whiteout”标记,屏蔽下层同名文件(overlay2 使用 .wh.* 文件)

为什么分层会影响构建效率和镜像大小层是缓存和复用的基本单位,但也是膨胀和冗余的源头。Docker 构建过程按指令逐层提交,一旦某层变化,其后所有层均失效重建;同时,被上层删除或覆盖的文件仍物理存在于旧层中,无法自动清理。

避免在不同层重复安装/删除软件包(如 apt update + apt install + apt clean 应写在同一 RUN 中)

使用多阶段构建(multi-stage build),仅将最终需要的二进制或配置复制到轻量运行镜像,丢弃构建依赖层docker image prune -a可清理悬空层(dangling layers),但不会删除被任意镜像引用的层实际验证:查看镜像层与存储布局以本地镜像为例,可通过文件系统路径观察真实分层结构(以 overlay2 驱动为例):镜像层元数据存于/var/lib/docker/image/overlay2/imagedb/content/sha256/,记录每层 diffID 和 chainID各层实际内容在/var/lib/docker/overlay2//diff/,对应文件差异树运行中容器的联合挂载点位于/var/lib/docker/overlay2//merged/,即你 exec 进去看到的根文件系统

相关文章