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

层数对当前和未来docker图像的大小、设置时间或性能有影响吗?,docker,docker-image,docker-layer,Docker,Docker Image,Docker Layer,假设我有两个选项来添加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层,而

假设我有两个选项来添加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图像的大小、设置时间或性能有影响吗


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

它确实会影响设置时间并可能影响大小。它不应该是性能,也就是说,性能是运行应用程序的实际性能

它确实会影响设置时间,因为定义的层越好,它们就越能用于其他图像。归根结底,一个层只是一个缓存,如果它可以为其他图像共享,构建时间就会缩短

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

要删除它,您有两个选项:

  • 您可以使用一个长期运行语句,在该语句中安装
    build-essential
    ,安装所需的软件包,然后删除
    build-essential
    ,所有这些都在同一个
    运行中
  • 只需使用多阶段,并有不同阶段的建设和运行

在实际层面上,尤其是在单层层面上,这没有什么区别。过去,一幅图像中有127层的限制;大多数实用的图像只有不到20个。原则上,如果有更多的Docker文件系统层,则遍历Docker文件系统层的速度可能会更慢,但Linux内核文件系统缓存适用,对于大多数性能敏感的事情来说,避免访问磁盘通常是最好的

与性能方面的考虑一样,如果这对您来说真的很重要,请在特定应用程序的上下文中对其进行度量

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

  • 添加一个层不会使图像变小。如果您在前面的
    运行
    步骤中安装了某个内容,然后在后面的
    运行
    步骤中将其删除,那么您的图像将包含前面层中所有已安装的内容,以及一个额外的占位符层,该占位符层显示“此内容现在已删除”。这尤其发生在构建工具周围@eez0在中对这种情况进行了更多的讨论

  • 层是Docker映像缓存的单位。如果重复一个
    Docker构建
    步骤,并且在已经存在的确切层上运行相同的命令,Docker将跳过实际运行该命令,并重新使用上一构建的结果层。这对Dockerfile样式有一些影响(如果您更改安装的软件包列表,您总是希望在同一个命令中
    运行apt get update&&apt get install
    ),但不会真正影响性能

  • 您可以
    docker运行
    单个步骤的结果。
    这是一种有用的调试技术:
    docker build
    的输出包括每个步骤的图像ID,您可以
    docker运行
    中间结果。如果某个步骤失败,您可以在映像上获得一个调试shell,直到该步骤开始,然后查看文件系统中的实际内容

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

    通常的做法是尝试将内容打包到一个
    RUN
    命令中,但这是一种微优化,在实践中通常不会产生太大的影响。在软件包安装的情况下,我习惯于在Dockerfile和style-wise中只看到一行
    apt get install
    pip install
    。如果您正处于开发过程中,那么每运行一行
    RUN
    命令更容易理解和调试