首页 > 解决方案 > 减少 Docker 容器大小

问题描述

我正在关注关于 Docker 的在线教程。作者举了一个例子:

FROM busybox
RUN dd if=/dev/zero of=/tmp/test1 bs=1M count=50
RUN dd if=/dev/zero of=/tmp/test2 bs=1M count=50
docker image ls
FROM busybox
RUN dd if=/dev/zero of=/tmp/test1 bs=1M count=50
RUN dd if=/dev/zero of=/tmp/test2 bs=1M count=50
RUN rm -rf /tmp/test1
RUN rm -rf /tmp/test2
docker image ls

为什么第二个 Dockerfile 显示的大小没有变小?

如何在不删除 RUN dd 命令的情况下使第二个 docker image ls 显示较小的图像?

标签: docker

解决方案


Docker 以及一般的容器引擎都使用联合挂载文件系统概念。
联合挂载是一种将多个目录组合成一个似乎包含其组合内容的方法。

因此,图像实际上由原子不可变文件夹(即“层”)组成。
该机制的主要目标是重复数据删除。
一层可以被多个图像共享,这样可以节省大量的存储容量。

例如。您下载 CenOS 基础镜像 (700 mb) 并在其上构建几个自定义镜像。
大的 CentOS 部分仍然存储一次 - 你的图像只是引用它。

另一个很好的答案- 旧的,但仍然相关。


当您使用 Dockerfile 构建映像时,Dockerfile 中的每个单独命令都会生成一个新层,将其置于前一层之上(或“合并”它们 - 就联合文件系统而言)。
生成的图像将包含在构建过​​程中创建的所有中间层。

FROM busybox
# layer 1: added test1 50 mb
RUN dd if=/dev/zero of=/tmp/test1 bs=1M count=50

# layer 2: added test2 50 mb
RUN dd if=/dev/zero of=/tmp/test2 bs=1M count=50

# layer 3: "removed" test1, but actually test1 still lives in layer 1
# "removal" just made it invisible for upper layers
# that is how removal works in union mount file systems
# technically, in terms of UFS, it's not a "removal", but a "merge" of layer 3 with layer 1
RUN rm -rf /tmp/test1

# layer 4: same as layer 3
RUN rm -rf /tmp/test2

节省空间的常用方法是在单个 RUN 指令下链接 shell 命令。

# in this case only one layer will be created
# it will contain eventual state of the filesystem after full command chain completion
RUN dd if=/dev/zero of=/tmp/test1 bs=1M count=50 && \
    dd if=/dev/zero of=/tmp/test2 bs=1M count=50 && \
    rm -rf /tmp/test1 && \
    rm -rf /tmp/test2

推荐阅读