在写 Dockerfile 的时候,很多人都会隐约记得一句话:
“每个 RUN 都会生成一层”
这句话基本正确,但不够完整。本文从 Docker 镜像层的上限说起,系统梳理 Dockerfile 各指令与镜像层之间的关系,并给出一些实战建议。
一、Docker 镜像最多能有多少层?
Docker 镜像并不是无限叠加的。
- 镜像层(image layers)最大约 125 层
- 容器运行时总层数(镜像层 + 可写层 + init 层)最大约 127 层
这个限制并非 Docker 人为设定,而是来自 OCI Image Spec 以及底层 UnionFS / OverlayFS 的实现约束。
一旦镜像层数超过限制,docker build 会直接失败。
二、Dockerfile 中:真的“每个 RUN 都是一层”吗?
结论是:大多数情况下是的,但并不只有 RUN 才会产生层。
会产生新层的常见指令
RUNCOPYADDENVLABELWORKDIRFROM(新 stage 的起点)
不会产生新层的指令
CMDENTRYPOINTARG(仅构建期可用)
也就是说,如果 Dockerfile 中指令很多,即便 RUN 数量不多,也可能不知不觉把层数堆上去。
三、最常见的“层数浪费”写法
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
这三行会生成 3 个层,而且中间层中的缓存实际上仍然存在。
更合理的写法是:
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
这样 只有 1 层,缓存也不会残留。
四、多阶段构建会不会影响层数限制?
会,但方式和很多人理解的不一样。
- 每个 stage 单独计算层数
- 最终镜像只包含最后一个 stage 的层
这也是为什么多阶段构建非常适合:
- 编译阶段随便折腾
- 运行时镜像保持极简
五、BuildKit 会不会突破层数上限?
不会。
BuildKit 主要优化的是:
- 构建缓存
- 并行执行
- cache 复用
但镜像层数上限依然存在。
六、如何查看一个镜像有多少层?
docker history your_image:tag
或者更直接一点:
docker inspect your_image:tag | jq '.[0].RootFS.Layers | length'
七、实践建议
- 合并
RUN - 合并包管理器操作(apt / yum / apk)
- 使用多阶段构建
- 编译与运行环境分离
- 运行时镜像尽量控制在 20 层以内
总结
- Docker 镜像并非无限叠加,层数存在硬上限
RUN基本都会生成一层,但并不只有RUN- 不合理的 Dockerfile 写法很容易“无感知地吃掉层数”
- 多阶段构建是解决层数与镜像体积问题的最优解