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

时间:2017-11-01 09:43:49

标签: shell docker dockerfile

Dockerfile中,我看到大多数人都使用这种语法

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

超过这个

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

对我来说,第一个只缓存一行(图层)而第二个缓存两个(我错了吗?)并在命令不成功时立即停止。

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

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

6 个答案:

答案 0 :(得分:2)

它是泊坞窗图像层的优化。我还建议您阅读Best practices for writing Dockerfiles

DockerCon EU 2017还有一些有趣的presentation

答案 1 :(得分:1)

图层越少,图像越好。

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

有两个RUN将创建两个层。

答案 2 :(得分:0)

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

组合命令是一种总体上减少层数的方法。

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

答案 3 :(得分:0)

这一行:

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

将创建一个泊坞窗图层和these lines

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

将创建两个不同的图层。

这就是为什么当您需要在docker机器中安装某些东西时(例如:通过APT),您倾向于将所有内容保存在一行(也称为图层)

答案 4 :(得分:0)

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

  

每个图层只是与之前图层的一组差异。这些层堆叠在彼此之上。创建新容器时,可在基础图层上添加新的可写层。

这意味着除非您要“挤压”您的图像(在构建过程中使用--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,缓存来自apt-get update
  • 安装了dnsutils
  • 1,
  • 1包含删除dnsutils
  • 1包含删除缓存

问题在于所有这些层都保留在那里并且毫无理由地消耗空间。

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

通常最好将操作相关的操作组合在操作系统上安装新包:

# 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"]

答案 5 :(得分:0)

根据images and layers documentation

  

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

因此,例如,2层创建不同的文件将不会使用更多的磁盘空间。特别是自Docker 17.05 allows multi-stage builds以来。但是,如果第二个完全修改第一个文件,它仍然可以使用更多空间。

关注Khapov Igor's comment我在best practice doc找到了原始问题的真实答案:

  

apt-get update语句中单独使用RUN会导致缓存问题和后续apt-get install条指令失败。

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

这就是他们说的原因:

  

始终将RUN apt-get updateapt-get install合并到同一RUN声明