是否可以删除 docker 镜像的中间层?

时间:2021-07-16 10:01:40

标签: docker

我想在不保留中间层的情况下逐步创建一个 docker 镜像。

我知道 docker 保留中间层是为了能够回滚到以前版本的镜像,但我对这个功能不感兴趣。

docker-squash 项目似乎提供了一个解决方案,但它已被归档并且没有维护 5 年。

这是一个简单的例子来解释我的意思

我有一个 72.7MB 的图片

image1                       latest            9873176a8ff5   4 weeks ago    72.7MB

我将一个 10MB 的文件添加到容器并将其提交到 image2

docker run -it image1 /bin/bash
truncate -s 10MB 10MB_FILE
docker cp 10MB_FILE container_id:/
docker commit -m "add 10MB" container_id image2

image2 重 10MB

image2                       latest            b7d1ea4043fb   58 seconds ago   82.7MB

我从容器中删除了 10MB 的文件并将其提交到 image3

docker run -it image2 /bin/bash
rm 10MB_FILE
exit
docker commit -m "remove fime" container_id image3

image3 重量相同

image3                       latest            11ff12ee0626   4 seconds ago    82.7MB

我想要一个 72.7MB 的 image3

我不想简单地还原提交,因为在添加文件和删除文件的提交之间可能还有其他一些提交要保留。

我知道我可以更改 Dockerfile 并从头开始重建(如回答 here),但有些安装需要花费大量时间。这就是我想使用 docker commit 增量创建 docker 映像的原因。

2 个答案:

答案 0 :(得分:1)

建议:创建您的版本“image1”的基础镜像。标记它并命名它。将其用作创建“image2”和“image3”的基础(来自 Dockerfile 中的 xyz)。在此之后,您应该能够实现您的目标。我打赌一品脱;-)

答案 1 :(得分:1)

您几乎不应该使用 docker commit。编写一个 Dockerfile 并将其签入源代码管理。

请注意,您的 image2 特别是使用 Dockerfile 非常容易描述,可能比创建容器、手动复制文件并提交更容易:

FROM image1
COPY 10MB_FILE /
# on the host system
truncate -s 10MB 10MB_FILE
docker build -t image2 .

现在假设您改变了对文件内容的看法。您根本不需要更改 Dockerfile;只需重新运行构建步骤。

# on the host system
# create a different 10 MB file
dd if=/dev/zero of=10MB_FILE bs=1M count=10
# build a new image
docker build -t image3 .

当你这样做时,你不必记住哪些图像是从哪些其他图像中构建的,以及使用了哪些步骤;它已在 Dockerfile 中为您记下。如果您仍在尝试弄清楚图像中包含的内容,那么编辑 Dockerfile 并在 docker build 上迭代直到正确为止没有任何问题。

另一个重要的细节是docker commit 总是使图像更大。新图像是未修改的原始图像,加上一张说明发生了什么变化的新图像。即使您删除文件(如最后一种情况),您的 image3 也是 image2,加上“这是一个新图层,其中包含文件被删除的详细信息”。

最后,您几乎肯定会在未来的某个时候重建这个镜像,如果没有别的原因,因为您的镜像堆栈基于 Linux 发行版,不可避免地会出现安全问题。如果您可以查看源代码并重新运行 docker build --pull -t image2 .,您就不需要记住这个非常手动的提交顺序。