背景介绍

《Dockerfile 相关》中提到,Dockerfile 中的部分指令(如 RUN、COPY、ADD)在构建 Docker 镜像时会增加镜像的层数。

本文将以 RUN 指令为例,进一步演示和分析其对 Docker 镜像层数的影响效果


演示过程

1、非精简指令构建镜像

  • Dockerfile-1 文件内容如下

# 指定基础镜像FROM alpine
# 指定 RUN 指令(两条命令,分别实现创建文件、删除文件)RUN echo "This is demo_content" > /tmp/1.txtRUN rm -rf /tmp/1.txt
  • 构建 Docker 镜像

docker build -t alpine:demo-1 -f Dockerfile-1 .
  • 查看 Docker 镜像分层信息

docker history alpine:demo-1 --no-trunc

  • 查看 Docker 镜像分层信息

  • 如图,该镜像有三个 layer 分层

    • 第一个分层:表示基础镜像

    • 第二个分层:对应第一条 RUN 指令,我们记录该镜像分层的 ID

    • 第三个分层:对应第二条 RUN 指令

alias dive="docker run -ti --rm -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive"dive alpine:demo-1

  • 查看 Docker 镜像分层文件

# 将 Docker 镜像保存为 tar 文件docker save alpine:demo-1 -o demo-1.tar # 查看 tar 文件内容tar -xf demo-1.tarcd 0e5986017b9df1a7163da7e70a44e72d951ddfebaf2b157eddcf00439bc76ebbtar -xf layer.tarcat tmp/1.txt

🔔 从图中可以看到,虽然镜像第三层对应的 RUN 指令删除了 1.txt 文件,但实际上该文件仍存在于镜像的第二层中,会占用镜像分层和本地空间。

2、精简指令构建镜像

  • Dockerfile-2 文件内容如下

# 指定基础镜像FROM alpine # 指定 RUN 指令(一条命令,实现创建文件、删除文件)RUN echo "This is demo_content" > /tmp/1.txt && rm -rf /tmp/1.txt
  • 构建 Docker 镜像

docker build -t alpine:demo-2 -f Dockerfile-2 .
  • 查看 Docker 镜像分层信息

docker history alpine:demo-2 --no-trunc

  • 查看 Docker 镜像分层信息

  • 如图,该镜像有两个 layer 分层

    • 第一个分层:表示基础镜像

    • 第二个分层:对应 RUN 指令,我们记录该镜像分层的 ID

alias dive="docker run -ti --rm -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive"dive alpine:demo-2

  • 查看 Docker 镜像分层文件

# 将 Docker 镜像保存为 tar 文件docker save alpine:demo-2 -o demo-2.tar # 查看 tar 文件内容tar -xf demo-2.tarcd 29baf2909e7a6a240ac1bb6e4bccd581a112a4a7e364a7f2b1f556fb0f652387tar -xf layer.tarcat tmp/1.txt

🔔 从图中可以看到,镜像第二层对应的 RUN 指令删除了 1.txt 文件,镜像的第二层中确实已经不存在该文件,不会占用镜像分层和本地空间。



写在最后

通过演示可知,使用精简指令确实可以有效减少不必要的镜像层数和过程文件。

为了实现 Dockerfile 的最佳实践,建议在 Dockerfile 中尽量使用 && 符号,将相关命令组合成单个 RUN 指令,以最大限度减少 RUN 指令数量和镜像层数,同理也要减少 COPY、ADD 指令的数量。这对于控制 Docker 镜像的大小、提高镜像构建和部署效率,以及通过避免创建可能包含敏感或冗余数据的不必要层来增强安全性至关重要。