为什么继承的Docker图像大小不同 [英] Why do inherited Docker images differ in size

查看:125
本文介绍了为什么继承的Docker图像大小不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近尝试了Docker。我试图建立一个像这样的图像架构,以便于维护和扩展。





我使用以下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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆