Dockerfile运行命令占用大量的磁盘空间

我有一个Dockerfile与这个RUN命令:

RUN ln -s /usr/java/jdk1.5.0_22 /usr/java/java-5-sun && \ ln -s /usr/java/jdk1.5.0_22 /usr/java/jdk1.5 && \ ln -s /usr/java/jdk1.6.0_45 /usr/java/java-6-sun && \ ln -s /usr/java/jdk1.6.0_45 /usr/java/jdk1.6 && \ ln -s /usr/java/jdk1.7.0_79 /usr/java/java-7-sun && \ ln -s /usr/java/jdk1.7.0_79 /usr/java/jdk1.7 && \ ln -s /usr/java/jdk1.8.0_60 /usr/java/java-8-sun && \ ln -s /usr/java/jdk1.8.0_60 /usr/java/jdk1.8 && \ chown -R user.root /usr/java 

但是,正如我从历史中看到的,它占用了大量的磁盘空间!

 /bin/sh -c ln -s /usr/java/jdk1.5.0_22 /usr/j 1.019 GB 

你知道为什么吗?

如果我正确地理解了这个问题,你想知道为什么这个特定的图像层是1 GiB的大小,当你所做的只是创build一些新的符号链接。 正确? (为什么四个不同的JDK的大小应该是不言自明的)。

关键是chown user.root /usr/java语句。 我强烈怀疑这个语句导致权限被改变的文件(也许是整个/usr/java目录)再次被添加到图像中的这个层。

你可以用一个非常简单的例子来validation这个行为。 考虑下面的Dockerfile

 FROM ubuntu:latest RUN echo foo > /tmp/bar RUN useradd foo RUN chown foo /tmp/bar 

现在用docker build构build这个镜像,然后用docker history <image-id>检查它。 docker history <image-id>

 IMAGE CREATED CREATED BY SIZE COMMENT fdd96781f94f 5 seconds ago /bin/sh -c chown foo /tmp/bar 4 B 7237dbee1999 6 seconds ago /bin/sh -c useradd foo 330.3 kB 69ed7323a0b0 6 seconds ago /bin/sh -c echo foo > /tmp/bar 4 B 17b6a9e179d7 5 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B b0c2dfa2701f 5 months ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB 202e40f8bb3a 5 months ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0 B acb8e44f43fa 5 months ago /bin/sh -c set -xe && echo '#!/bin/sh' > /u 701 B 487bffc61de6 5 months ago /bin/sh -c #(nop) ADD file:ffc85cfdb5e66a5b4f 120.8 MB 

使用最上层的ID( /bin/sh -c chown foo /tmp/bar )并在/var/lib/docker/aufs/diff/<ID>...查找此ID(假设您正在使用AUFS作为存储驱动程序):

 $ find /var/lib/docker/aufs/diff/fdd96781f94feee4a6db44b11f7f9411c52238458ceeef202b2203e77b9970f4 /var/lib/docker/aufs/diff/fdd96781f94feee4a6db44b11f7f9411c52238458ceeef202b2203e77b9970f4 /var/lib/docker/aufs/diff/fdd96781f94feee4a6db44b11f7f9411c52238458ceeef202b2203e77b9970f4/tmp /var/lib/docker/aufs/diff/fdd96781f94feee4a6db44b11f7f9411c52238458ceeef202b2203e77b9970f4/tmp/bar 

如您所见,在构build过程中更改文件的权限会导致在下一个图像层中再次添加该文件。 更改所有Java SDK的权限,使其全部(大小约1 GiB)被添加到其他图像层。