为什么&&而不是一个新的运行

Dockerfile我看到了大多数使用这种语法的人

 RUN apt-get -y update \ && apt-get install -y libicu-dev 

在这一个

 RUN apt-get -y update RUN apt-get install -y libicu-dev 

对于我来说,第一个只有一行(层)caching,而第二个caching(我错了吗?),一旦命令不成功就停下来。

除此之外,我没有发现第一个更具可读性。

那么我们为什么要使用第一个语法呢?

这是docker图像层的优化。 我也推荐阅读编写Dockerfiles的最佳实践

DockerCon欧盟2017也有趣的演示 。

层次越less,图像越好。

因此,使用&&组合命令将创build一个单一的图层。

有两个RUN将创build两个层。

Dockerfile中的每个命令都会创build另一个图像层

组合命令是一种最终减less总体层数的方法。

请参阅https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/#images-and-layers

这一行:

 RUN apt-get -y update \ && apt-get install -y libicu-dev 

将创build一个单一的docker层和这些行 :

 RUN apt-get -y update RUN apt-get install -y libicu-dev 

将创build两个不同的层。

这就是为什么当你需要在Docker机器上安装某些东西的时候(例如:通过APT),你往往把所有东西都放在一个单独的行中(又称为层)

正如其他答案已经说过的,每个命令都会生成一个图层,通常希望每个图像的图层数量最less。

每一层只是一个与它之前的层的差异。 这些图层堆叠在一起。 当你创build一个新的容器时,你在底层上添加一个新的可写层。

这意味着,除非你打算“挤压”你的图像(这意味着在构build过程中使用了--squash选项), --squash最终会产生一个图像消耗空间。

 # Dockerfile FROM ubuntu RUN apt-get update RUN apt-get install -y --no-install-recommends dnsutils RUN echo $( dig somewhere.nowhere ) RUN apt-get remove --purge dnsutils RUN rm -rf /var/lib/apt/lists/* COPY magicalScript.sh / CMD /magicalScript.sh 

在这种情况下,您将只包含开销的图层:

  • 1的caching来自apt-get update
  • 1与dnsutils安装,
  • 1包含去除dnsutils
  • 1包含删除caching

问题是,所有这些层都保留在那里,而且完全没有理由占用空间。

为什么squash并不总是一个好的解决scheme? 因为这些图层也代表caching。 当你需要执行大量的构build时,它非常有用,而且你需要它们尽可能快。

通常在OS上将新软件包的安装相关的操作分组是很好的做法:

 # Dockerfile FROM ubuntu RUN useradd docker \ && mkdir /home/docker \ && chown docker:docker /home/docker \ && addgroup docker staff RUN apt-get update \ && apt-get install -y --no-install-recommends ed less locales vim-tiny wget ca-certificates fonts-texgyre \ && rm -rf /var/lib/apt/lists/* RUN echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \ && locale-gen en_US.utf8 \ && /usr/sbin/update-locale LANG=en_US.UTF-8 CMD ["mySpecialCommand"] 

根据图像和图层文件

每一层只是一个与它之前的层的差异

所以例如2层创build不同的文件不会使用更多的磁盘空间。 特别是因为Docker 17.05 允许多阶段构build 。 但是,如果第二个文件完全从第一个文件修改,它仍然可以使用更多的空间。

按照Khapov Igor的评论,我在最佳实践文档中发现了原始问题的真实答案:

RUN语句中单独使用apt-get update会导致caching问题,并且随后的apt-get install指令会失败。

实际上更多的是关于以前的命令的层依赖关系,结果可以像apt-get update一样随着时间的推移而发展。

这就是为什么他们说:

在同一个RUN语句中总是将RUN apt-get updateapt-get install结合起来