DockerFile 单行 vs 多行指令

Sag*_*off 2 docker dockerfile

据我所知 docker build 的工作方式是,对于每一行指令,它都会创建一个单独的图像/层。但是,在管理重用层或避免在没有任何更改的情况下重建这些层方面非常有效。

那么我将下面的指令放在同一行还是多行上有关系吗?为方便起见,我更喜欢单行选项,除非它不是一个有效的选项。

多行指令

RUN apt-get -y update
RUN apt-get -y install ...
Run Code Online (Sandbox Code Playgroud)

单行指令

RUN apt-get -y update && apt-get -y install
Run Code Online (Sandbox Code Playgroud)

Dav*_*aze 5

在这种特定的情况下,把重要的是apt-get updateapt-get install在一起。更广泛地说,较少的层被认为是“更好的”,但它几乎从来没有明显的差异。

在实践中,我倾向于将“相关”命令组合到同一个RUN命令中。如果我需要从源代码配置和安装一个包,它可以组合在一起,即使我更改了make参数,我也不介意重新运行configure. 如果我需要配置和安装三个包,它们会进入不同的RUN行。

这个特定apt-get示例的重要区别在于层缓存。假设您的 Dockerfile 有

FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install package-a
Run Code Online (Sandbox Code Playgroud)

如果你docker build第二次运行,它会决定它已经运行了所有这三个命令并且输入没有改变,所以它会运行得非常快,你会得到一个相同的图像。

现在你一两天后回来,意识到你错过了一些东西,所以你改变了

FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install package-a package-b
Run Code Online (Sandbox Code Playgroud)

当您docker build再次运行时,Docker 确定它已经运行apt-get update并且可以直接跳到该apt-get install行。在这种特定情况下,您会遇到麻烦:Debian 和 Ubuntu 更新它们的存储库相当频繁,并且当它们更新时,旧版本的软件包会被删除。所以你apt-get update两天前指向一个不再存在的包,你的构建将失败。

通过始终将两个apt-get命令放在同一docker run行中,您将避免此特定问题

FROM ubuntu:18.04
RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install --assume-yes --no-install-recommends \
      package-a \
      package-b
Run Code Online (Sandbox Code Playgroud)