2

假设我有 2 个选项来添加 docker 层。

选项1:

RUN python -m nltk.downloader punkt averaged_perceptron_tagger brown

选项2:

RUN python -m nltk.downloader punkt 
RUN python -m nltk.downloader brown
RUN python -m nltk.downloader averaged_perceptron_tagger 

我知道第二个选项增加了 3 层,而第一个选项只增加了 1 层。

层数是否对当前和未来 docker 镜像的大小、设置时间或性能有影响?

注意:当前是指当前图像。未来意味着任何可能使用现有图像中的某些层的图像,从而加快设置速度。

4

2 回答 2

2

它确实会影响设置时间并可能影响大小。它不应该是性能,这意味着性能是正在运行的应用程序的实际性能。

它确实会影响设置时间,因为您定义的层越好,它们就可以更好地用于其他图像。归根结底,一个层只是一个缓存,如果它可以共享给其他图像,构建时间将会得到改善。

关于大小,这实际上取决于您如何构建图像。例如,如果您有运行时不需要的构建依赖项,则映像会更大,因为它将具有此类依赖项。说到 python,通常你会想要安装build-essential来构建你的应用程序,但是,一旦安装了包,你就不再需要build-essential. 如果你不删除它,图像会更大。

要删除它,您有两种选择:

  • 要么你使用一个很长的 RUN 语句来安装build-essential,安装你需要的包,然后删除 build-essential,所有这些都在同一个RUN.
  • 只需使用多阶段,并有不同的阶段来构建和运行。
于 2020-02-10T09:41:27.517 回答
1

在实践层面,尤其是在单层层面,它没有任何区别。图像中曾经有 127 层的记录限制;大多数实用的镜像少于 20 个。原则上,如果有更多的 Docker 文件系统层,通过它们可能会更慢,但是 Linux 内核文件系统缓存适用,并且对于大多数性能敏感的东西,最好完全避免进入磁盘.

一如既往地考虑性能,如果它对您真的很重要,请在您的特定应用程序的上下文中对其进行衡量。

我想说,关于 Docker 镜像层,需要牢记三件事:

  1. 添加图层永远不会使图像变小。 如果您在前面的RUN步骤中安装了某些东西,并在后面的步骤中将其删除,那么RUN您的图像最终会包含来自早期层的所有已安装内容,以及一个额外的占位符层,上面写着“这些东西现在已被删除”。这尤其发生在构建工具周围。@eez0 在他们的回答中更多地讨论了这个案例。

  2. 层是 Docker 图像缓存的单元。 如果您重复一个docker build步骤,并且在已经存在的确切层上运行相同的命令,Docker 将跳过实际运行它并重用先前构建的结果层。这对 Dockerfile 样式有一些影响(您总是希望RUN apt-get update && apt-get install在同一个命令中,以防您更改要安装的软件包列表),但不会真正影响性能。

  3. 您可以docker run得到单个步骤的结果。 这是一种有用的调试技术:docker build每个步骤的输出都包含一个图像 ID,您可以获得docker run中间结果。如果某个步骤失败,您可以在该步骤开始之前在映像上获取一个调试 shell,并查看文件系统中的实际内容。

在您的示例中,值得问的两个问题是单个下载器步骤有多少开销,以及这组插件更改的可能性有多大。如果您可能经常更改内容,单独的RUN命令可以让您在以后的构建中更好地缓存图层;如果下载工具本身的开销很大(也许它将所有下载的插件组装到一个 zip 文件中),那么只运行一次可能会更快。

通常的做法是尝试将东西打包到一个RUN命令中,但这是一种微优化,通常不会在实践中产生太大影响。在安装包的情况下,我习惯于在 Dockerfile 中只看到一行apt-get install或一行,而且从风格上讲,我可能也希望在这里。pip install如果您正在开发事物,则每RUN行一个命令更容易理解和调试。

于 2020-02-10T10:51:29.060 回答