为什么继承的Docker图像大小不同 [英] Why do inherited Docker images differ in size
问题描述
我使用以下Dockerfiles构建了图像,并对不同的容器大小感到好奇。为什么他们有这么大的不同?
以下 base / Dockerfile 导致 210.9 MB 图像(ubuntu:trusty有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
#+来自apache / Dockerfile的最后7行
到目前为止还没有用,直到现在还没有使用继承。我们来看看:
为什么 apache-php-on-base / Dockerfile 导致 289.4 MB ?它基本上是相同的步骤,但拆分成两个图像。我会期望有一点开销,但不是约10%。
FROM base
#+ apache-php / Dockerfile没有安装nano
使用多重继承更大: apache-php-on- apache-on-base / Dockerfile 导致 314.9 MB 。
FROM apache-基础
#+ apache-php / Dockerfile没有安装nano apache2
其中 apache-on-base / Dockerfile 当然(导致 247 MB ):
FROM base
#+ apache / Dockerfile没有安装nano
问题:是否有一种防止图像增长的方法,同时保持可维护性?
更新:实现thaJeztah的建议我收到以下:)再次感谢!
REPOSITORY TAG IMAGE I D CREATED SIZE
apache-php-on-aob最新的2cf12a3b5872 2分钟前249.9 MB
apache-on-base最新的121c8a098ff5 3分钟前203.7 MB
base最新ee95e4f8aaee 3分钟前189.3 MB
apache-php-on-aob v1 e43df5e61aed 3天前314.9 MB
apache-on-base v1 c291f91f1a10 3天前247 MB
base v1 b181fc6f181d 3天前210.9 MB
ubuntu trusty 97434d46f197 10天前188 MB
不经过所有深度差异,最有可能的原因是
您没有考虑分层文件系统。
Docker创建一个新的 imagelayer为您的Docker文件中的每个指令。基本上
发生什么(非常简化):
所以,这将成为第一层:
FROM ubuntu:trusty
(Docker做某事喜欢)
Docker build -t layer1。
这将成为第二层:
FROM layer1
RUN apt-get -qq update&& \
DEBIAN_FRONTEND = noninteractive apt-get -qq install \
nano
Docker build -t layer2。
等等。
图像是所有这些图像堆叠的组合。实现
的重要事情是,在layer2
中的layer1中添加但删除的文件仍然是图像的一部分; Docker只将它标记为layer2中的删除,但是
不会使图像更小。
我们来看看你的第一个Dockerfile。您可以看到,在第一个 RUN
指令中添加
个文件,然后添加一个仅设置
an ENV
var,其次是另一个 RUN
,可以将所有冗余文件
从首先 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 / *
建立后( docker build -t foobar。
),这给了我:
REPOSITORY TAG IMAGE ID CREATED SIZE
foobar最新363aa5572838 2分钟前210.9 MB
进行一个小的改动,并结合两个 RUN
指令,以便
apt-get update
和 apt-get clean
步骤发生在相同的 RUN
中,所以
相同的层
FROM ubuntu:trusty
RUN apt-get - qq更新&& \
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
创建此图像:
REPOSITORY TAG IMAGE ID创建的大小
foobar最新ac8fb5e4db16 9分钟前189.3 MB
这是20MB小!
您可以在 Dockerfile中阅读更多信息最佳做法
部分文件。
I'm lately experimenting with Docker. I try to build an image architecture looking like this for easy maintenance and extensibility.
I built images with following Dockerfiles and am curious about different container sizes. Why do they differ this much?
Following base/Dockerfile results in a 210.9 MB image (ubuntu:trusty having 188 MB so that's okay).
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 results in 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 results in 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
That's fine so far but we haven't used inheritance until now. Let's have a look:
Why does apache-php-on-base/Dockerfile result in 289.4 MB? It's basically the same steps but split in two images. I would have expected a little overhead but not about 10 %.
FROM base
# + apache-php/Dockerfile without "install nano"
It's even bigger using multiple inheritance: apache-php-on-apache-on-base/Dockerfile results in 314.9 MB.
FROM apache-on-base
# + apache-php/Dockerfile without "install nano apache2"
Where apache-on-base/Dockerfile is of course (resulting in 247 MB):
FROM base
# + apache/Dockerfile without "install nano"
Question: Is there a way preventing images from growing this large while preserving maintainability?
Update: Implementing thaJeztah's suggestions I got following :) Thanks again!
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
Without going through all differences in depth, the most likely reason is that you're not taking the layered filesystem into account.
Docker creates a new imagelayer for each instruction in your Dockerfile. Basically what happens is (very much simplified):
So, this will become the first layer:
FROM ubuntu:trusty
(And Docker does something like)
Docker build -t layer1 .
This will become the second layer:
FROM layer1
RUN apt-get -qq update && \
DEBIAN_FRONTEND=noninteractive apt-get -qq install \
nano
(And Docker does something like)
Docker build -t layer2 .
And so on.
The final image is a combination of all those images "stacked". The important thing to realize there is that a file that's added in "layer1", but removed in "layer2" is still part of the image; Docker only marks it as "removed" in layer2, but that doesn't make the image smaller.
Let's have a look at your first Dockerfile. As you can see you're adding a lot
of files in the first RUN
instruction, then add an empty layer that only sets
an ENV
var, followed by another RUN
that removes all the redundant files
from the first RUN
. However, those files aren't removed from the earlier layer,
so still take up space in the final image;
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/*
After building (docker build -t foobar .
), this gives me:
REPOSITORY TAG IMAGE ID CREATED SIZE
foobar latest 363aa5572838 2 minutes ago 210.9 MB
Making a small change, and combine the two RUN
instructions, so that both the
apt-get update
and apt-get clean
steps take place in the same RUN
, so
the same layer;
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
And building that, produces this image:
REPOSITORY TAG IMAGE ID CREATED SIZE
foobar latest ac8fb5e4db16 9 minutes ago 189.3 MB
That's 20MB smaller!
You can read more about this in the Dockerfile best practice section of the documentation.
这篇关于为什么继承的Docker图像大小不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!