2.4. 使用多阶段构建自定义可引导镜像的好处
部署镜像必须只包含应用程序及其所需的运行时,而无需添加任何构建工具或不必要的库。要达到此目的,请使用两阶段 Containerfile
: 一个阶段来构建工件,另一个用于托管应用程序。
使用多阶段构建时,您可以在 Containerfile
中使用多个 FROM
指令。每个 FROM
指令都可以使用不同的基础,每个基础都开始构建的新阶段。您可以选择将工件从一个阶段复制到另一个阶段,并排除您在最终镜像中不需要的所有内容。
多阶段构建提供了几个优点:
- 较小的镜像大小
- 通过将构建环境与运行时环境分开,最终镜像中仅包含必要的文件和依赖项,从而显著降低其大小。
- 提高了安全性
- 由于构建工具和不必要的库没有包括在最终镜像中,因此攻击面会减少,从而导致更安全的容器。
- 优化的性能
- 较小的镜像大小意味着更快地下载、部署和启动时间,从而提高了容器化应用的整体效率。
- 简化维护
- 当构建和运行时环境分隔时,最终镜像会更加干净,更易于维护,仅包含运行应用程序所需的内容。
- 清理构建
- 多阶段构建有助于避免中间文件出现问题,这些文件可能在构建过程中累积,确保只有基本工件使它成为最终镜像。
- 资源效率
- 在一个阶段构建并丢弃不必要的部分的功能,可以最大程度降低部署期间使用存储和带宽。
- 更好的层缓存
- 通过明确定义的阶段,Podman 可以有效地缓存之前阶段的结果,从而可能会加快未来的构建。
以下 Containerfile
由两个阶段组成。第一个阶段通常命名为 builder
,它编译了 golang 二进制文件。第二阶段从第一阶段复制 二进制文件。go-toolset 构建器的默认工作目录是 opt/ap-root/src
。
因此,最终的容器镜像包含 helloworld
二进制文件,但没有来自上一阶段的数据。
您还可以使用多阶段构建来执行以下操作:
- 在特定的构建阶段停止
- 在构建镜像时,您可以在指定的构建阶段停止。例如:
podman build --target build -t hello .
$ podman build --target build -t hello .
例如,您可以使用这种方法调试特定的构建阶段。
- 使用外部镜像作为阶段
-
您可以使用
COPY --from
指令从单独的镜像复制,使用本地镜像名称、本地可用的标签或容器 registry 中的标签 ID。例如:
COPY --from=<image> <source_path> <destination_path>
COPY --from=<image> <source_path> <destination_path>
- 使用前一个阶段作为新阶段
-
您可以使用
FROM
指令继续结束之前阶段的位置。示例: