你确定你会写 Dockerfile 吗?

  • 时间:
  • 浏览:8
  • 来源:老李博客 - 专注共享凌空博客资讯

镜像的构建顺序很重要,当你向 Dockerfile 中添加文件,机会修改其中的某一行时,那一次责的缓存就会失效,该缓存的后续步骤后会中断,还要重新构建。什么都 优化缓存的最佳措施是把不还要总爱更改的行装入 最前面,更改最频繁的行装入 最上方。

本文从在非一致性环境中构建体积较大的镜像现在开始英语 英语 优化,总爱优化到在一致性环境中构建最小镜像,一起充分利用了缓存机制。下一篇文章机会介绍多阶段构建的更多其他用途。

基础镜像尽量何必 使用 latest 标签。觉得这很方便,但随着时间的推移,latest 镜像机会会发生重大变化。也没法 Dockerfile 中最好指定基础镜像的具体标签。其他人使用 openjdk 作为示例,指定标签为 8。其他更多标签请查看官方仓库。

到目前为止,其他人总爱算是假设你的 jar 包是在主机上构建的,这还算是理想方案,机会没法 充分利用容器提供的一致性环境。这个,机会你的 Java 应用依赖于某有有一个特定的操作系统的库,就机会会老出 问题图片,机会环境不一致(具体取决于构建 jar 包的机器)。

多阶段构建是删除构建依赖的首选方案。

基础镜像的标签风格不同,镜像体积就会不同。slim 风格的镜像是基于 Debian 发行版制作的,而 alpine 风格的镜像是基于体积更小的 Alpine Linux 发行版制作的。其饱含 晒 一个明显的区别是:Debian 使用的是 GNU 项目所实现的 C 语言标准库,而 Alpine 使用的是 Musl C 标准库,它被设计用来替代 GNU C 标准库(glibc)的替代品,用于嵌入式操作系统和移动设备。可是我使用 Alpine 在其他情况汇报下会遇到兼容性问题图片。 以 openjdk 为例,jre 风格的镜像只饱含 Java 运行时,不饱含  SDK,没法 做可是我能大大减少镜像体积。

首先应该选则构建应用所需的所有依赖,本文的示例 Java 应用很简单,只还要 Maven 和 JDK,什么都 基础镜像应该选则官方的体积最小的 maven 镜像,该镜像也饱含 了 JDK。机会你还要安装更多依赖,不能在 RUN 指令中添加。pom.xml文件和 src 文件夹还要被克隆到镜像中,机会最后执行 mvn package 命令(-e 参数用来显示错误,-B 参数表示以非交互式的“批处里”模式运行)打包的让你会用到那些依赖文件。

每有有一个 RUN 指令后会被看作是可缓存的执行单元。太少的 RUN 指令会增加镜像的层数,增大镜像体积,而将所有的命令都装入 同有有一个 RUN 指令中又会破坏缓存,从而延缓开发周期。当使用包管理器安装软件时,一般后会先更新软件索引信息,可是我再安装软件。推荐将更新索引和安装软件装入 同有有一个 RUN 指令中,从前不能形成有有一个可缓存的执行单元,可是我你机会会安装旧的软件包。

本文使用有有一个基于 Maven 的 Java 项目作为示例,可是我让断改进 Dockerfile 的写法,直到最后写出有有一个最优雅的 Dockerfile。上方的所有步骤算是为了说明某一方面的最佳实践。

觉得现在其他人处里了环境不一致的问题图片,但还有另外有有一个问题图片:每次代码更改让你,算是重新获取一遍 pom.xml 中描述的所有依赖项。下面其他人来处里这个问题图片。

源代码你没法构建 Docker 镜像的最终来源,Dockerfile 上方只提供了构建步骤。

使用官方镜像不能节省极少量的维护时间,机会官方镜像的所有安装步骤都使用了最佳实践。机会你有多个项目,不能共享那些镜像层,机会其他人都不能使用相同的基础镜像。

删除何必 要的依赖,何必 安装调试工具。机会觉得还要调试工具,不能在容器运行让你再安装。其他包管理工具(如 apt)除了安装用户指定的包之外,后会安装推荐的包,这会总爱增加镜像的体积。apt 不能通过添加参数 -–no-install-recommends 来确保不让安装不还要的依赖项。机会觉得还要其他依赖项,请在上方手动添加。

多阶段构建不能由多个 FROM 指令识别,每有有一个 FROM 一句话表示有有一个新的构建阶段,阶段名称不能用 AS 参数指定。本例中指定第一阶段的名称为 builder,它不能被第二阶段直接引用。有有一个阶段环境一致,可是我第一阶段饱含 所有构建依赖项。

包管理工具会维护个人的缓存,那些缓存会保留在镜像文件中,推荐的处里措施是在每有有一个 RUN 指令的末尾删除缓存。机会你在下第一根指令中删除缓存,不让减小镜像的体积。

当拷贝文件到镜像中时,尽量只拷贝还要的文件,切忌使用 COPY . 指令拷贝整个目录。机会被拷贝的文件内容发生了更改,缓存就会被破坏。在上方的示例中,镜像中只还要构建好的 jar 包,可是我只还要拷贝这个文件就行了,从前即使其他不相关的文件发生了更改可是我让影响缓存。

现在又遇到了有有一个新问题图片:跟让你直接拷贝 jar 包相比,镜像体积变得更大了,机会它饱含 了什么都 运行应用时不还要的构建依赖项。

原文链接:你选则可是我你写 Dockerfile 吗?

结合前面提到的缓存机制,其他人不能让获取依赖项这个步变成可缓存单元,可是我 pom.xml 文件的内容没法 变化,无论代码怎样更改,算是会破坏这个层的缓存。上图饱含 晒 一个 COPY 指令上方的 RUN 指令用来告诉 Maven 只获取依赖项。

有有一个开发周期包括构建 Docker 镜像,更改代码,可是我重新构建 Docker 镜像。在构建镜像的过程中,机会不能利用缓存,不能减少何必 要的重复构建步骤。

镜像的体积很重要,机会镜像越小,部署的时延更快,攻击范围越小。

第二阶段是构建最终镜像的最后阶段,它将包括应用运行时的所有必要条件,本例是基于 Alpine 的最小 JRE 镜像。上有有一个构建阶段觉得会有极少量的缓存,但不让老出 在第二阶段中。为了将构建好的 jar 包添加到最终的镜像中,不能使用 COPY --from=STAGE_NAME 指令,其中 STAGE_NAME 是上一构建阶段的名称。

当然了,还有其他更高级的措施不能用来减小镜像体积,如下文机会介绍的多阶段构建。接下来其他人将探讨怎样优化 Dockerfile 的可维护性、安全性和可重复性。

如今 GitHub 仓库中机会饱含 了成千上万的 Dockerfile,但并算是所有的 Dockerfile 算是高效的。本文将从有一个方面来介绍 Dockerfile 的最佳实践,以此来帮助其他人编写更优雅的 Dockerfile。机会你是 Docker 的初学者,恭喜你,这篇文章可是我为你准备的。上方的系列机会更加深入,敬请期待!