在实践层面,尤其是在单层层面,它没有任何区别。图像中曾经有 127 层的记录限制;大多数实用的镜像少于 20 个。原则上,如果有更多的 Docker 文件系统层,通过它们可能会更慢,但是 Linux 内核文件系统缓存适用,并且对于大多数性能敏感的东西,最好完全避免进入磁盘.
一如既往地考虑性能,如果它对您真的很重要,请在您的特定应用程序的上下文中对其进行衡量。
我想说,关于 Docker 镜像层,需要牢记三件事:
添加图层永远不会使图像变小。 如果您在前面的RUN
步骤中安装了某些东西,并在后面的步骤中将其删除,那么RUN
您的图像最终会包含来自早期层的所有已安装内容,以及一个额外的占位符层,上面写着“这些东西现在已被删除”。这尤其发生在构建工具周围。@eez0 在他们的回答中更多地讨论了这个案例。
层是 Docker 图像缓存的单元。 如果您重复一个docker build
步骤,并且在已经存在的确切层上运行相同的命令,Docker 将跳过实际运行它并重用先前构建的结果层。这对 Dockerfile 样式有一些影响(您总是希望RUN apt-get update && apt-get install
在同一个命令中,以防您更改要安装的软件包列表),但不会真正影响性能。
您可以docker run
得到单个步骤的结果。 这是一种有用的调试技术:docker build
每个步骤的输出都包含一个图像 ID,您可以获得docker run
中间结果。如果某个步骤失败,您可以在该步骤开始之前在映像上获取一个调试 shell,并查看文件系统中的实际内容。
在您的示例中,值得问的两个问题是单个下载器步骤有多少开销,以及这组插件更改的可能性有多大。如果您可能经常更改内容,单独的RUN
命令可以让您在以后的构建中更好地缓存图层;如果下载工具本身的开销很大(也许它将所有下载的插件组装到一个 zip 文件中),那么只运行一次可能会更快。
通常的做法是尝试将东西打包到一个RUN
命令中,但这是一种微优化,通常不会在实践中产生太大影响。在安装包的情况下,我习惯于在 Dockerfile 中只看到一行apt-get install
或一行,而且从风格上讲,我可能也希望在这里。pip install
如果您正在开发事物,则每RUN
行一个命令更容易理解和调试。