为什么inheritance的Docker镜像的大小不同

我最近正在试验Docker。 我尝试构build一个像这样的图像架构,以便于维护和扩展。

建筑

我用下面的Dockerfiles构build了图像,并对不同的容器大小感到好奇。 为什么他们差异很大?

以下基地/ Dockerfile结果在一个210.9 MB的图像(Ubuntu的:可靠有188 MB,所以没关系)。

FROM ubuntu:trusty RUN apt-get -qq update && \ DEBIAN_FRONTEND=noninteractive apt-get -qq install \ nano ENV TERM xterm RUN apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

apache / Dockerfile结果为224.4 MB

 FROM ubuntu:trusty RUN apt-get -qq update && \ DEBIAN_FRONTEND=noninteractive apt-get -qq install \ nano \ apache2 ENV TERM xterm RUN apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* COPY apache2-foreground /usr/local/bin/ RUN chmod a+x /usr/local/bin/apache2-foreground EXPOSE 80 WORKDIR /var/www/html CMD ["apache2-foreground"] 

apache-php / Dockerfile结果为266.7 MB

 FROM ubuntu:trusty RUN apt-get -qq update && \ DEBIAN_FRONTEND=noninteractive apt-get -qq install \ nano curl \ apache2 \ libapache2-mod-php5 php5-mysql php5-mcrypt php5-gd php5-curl php-pear php-apc && \ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN /usr/sbin/php5enmod mcrypt # + last 7 lines from apache/Dockerfile 

到目前为止还好,但是到现在为止我们还没有使用过inheritance。 我们来看一下:

为什么apache-php-on-base / Dockerfile结果是289.4 MB ? 这基本上是相同的步骤,但分成两个图像。 我会期望有一点点的开销,但不是10%左右。

 FROM base # + apache-php/Dockerfile without "install nano" 

它使用多重inheritance更大: apache-php-on-apache-on-base / Dockerfile结果为314.9 MB

 FROM apache-on-base # + apache-php/Dockerfile without "install nano apache2" 

在哪里apache-on-base / Dockerfile当然是(导致247 MB ):

 FROM base # + apache/Dockerfile without "install nano" 

问题:在保持可维护性的同时防止图像增长过大吗?

更新:实现thaJeztah的build议,我得到了:)再次感谢!

 REPOSITORY TAG IMAGE ID CREATED SIZE apache-php-on-aob latest 2cf12a3b5872 2 minutes ago 249.9 MB apache-on-base latest 121c8a098ff5 3 minutes ago 203.7 MB base latest ee95e4f8aaee 3 minutes ago 189.3 MB apache-php-on-aob v1 e43df5e61aed 3 days ago 314.9 MB apache-on-base v1 c291f91f1a10 3 days ago 247 MB base v1 b181fc6f181d 3 days ago 210.9 MB ubuntu trusty 97434d46f197 10 days ago 188 MB 

没有经历深度的所有差异,最可能的原因是您没有考虑分层文件系统。

Docker为Dockerfile中的每条指令创build一个的图层。 基本上发生了什么(非常简化):

所以,这将成为第一层:

 FROM ubuntu:trusty 

(和Docker做的一样)

 Docker build -t layer1 . 

这将成为第二层:

 FROM layer1 RUN apt-get -qq update && \ DEBIAN_FRONTEND=noninteractive apt-get -qq install \ nano 

(和Docker做的一样)

 Docker build -t layer2 . 

等等。

最终的图像是所有这些“堆叠”图像的组合。 要实现的重要一点是,在“layer1”中添加但在“layer2”中删除的文件仍然是图像的一部分; Docker只会在layer2中将其标记为“已删除”,但不会使图像变小。

我们来看看你的第一个Dockerfile。 正如你所看到的,你在第一个RUN指令中增加了很多文件,然后添加一个空的层,它只设置一个ENV var,接着是另一个RUN ,从第一个RUN中删除所有的冗余文件。 但是,这些文件并没有从较早的图层中删除,因此在最终图像中仍占用空间;

 FROM ubuntu:trusty RUN apt-get -qq update && \ DEBIAN_FRONTEND=noninteractive apt-get -qq install \ nano ENV TERM xterm RUN apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

在build立之后( docker build -t foobar . ),这给了我:

 REPOSITORY TAG IMAGE ID CREATED SIZE foobar latest 363aa5572838 2 minutes ago 210.9 MB 

做一个小小的改变,合并两条RUN指令,这样apt-get updateapt-get clean都会在同一个 RUN ,所以一层;

 FROM ubuntu:trusty RUN apt-get -qq update && \ DEBIAN_FRONTEND=noninteractive apt-get -qq install \ nano && \ apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ENV TERM xterm 

而build设,产生这样的形象:

 REPOSITORY TAG IMAGE ID CREATED SIZE foobar latest ac8fb5e4db16 9 minutes ago 189.3 MB 

这是20MB的小!

您可以在文档的Dockerfile最佳实践部分阅读更多信息。