Docker 多阶段构建指南
Last updated
Was this helpful?
Last updated
Was this helpful?
多阶段构建(Multi-Stage Builds)是一种 Docker 构建技巧,它允许你在 Dockerfile 中定义多个 FROM
指令,每个阶段都可以用不同的基础镜像和构建步骤。这种方法可以有效地减小 Docker 镜像的大小,并且使得构建过程更加高效。
减小镜像体积:通过仅保留最终所需的文件和依赖,可以避免将不必要的构建工具和临时文件包含到最终镜像中。
简化 Dockerfile:多阶段构建可以将不同的构建步骤分离开,使 Dockerfile 更加清晰和易于管理。
提高安全性:只将必要的文件和依赖打包到生产环境镜像中,减少潜在的安全风险。
在 Dockerfile 中,你可以使用多个 FROM
指令,每个指令都标志着一个新的构建阶段。你可以从一个阶段复制文件到另一个阶段,这样可以在多个阶段之间共享文件。
每个阶段都可以有独立的基础镜像,而最终的镜像只会包含最后一个阶段的文件。
下面是一个常见的多阶段构建示例,它演示了如何构建一个 Node.js 应用,并确保最终镜像只有应用代码和必需的依赖,而没有开发工具和构建文件。
阶段 1 - builder
:
使用 node:14
镜像作为基础镜像,安装项目依赖,构建源代码。
在这一阶段,安装所有的开发依赖(如构建工具、TypeScript 等),并将构建后的文件保存在 /app/dist
目录中。
阶段 2 - 生产镜像:
使用 node:14-slim
作为基础镜像,它比 node:14
镜像更小,去除了很多不必要的工具。
从第一阶段(builder
)复制构建后的代码(/app/dist
)和生产依赖(/app/node_modules
)。
只有运行时所需的文件和依赖被包含在最终镜像中,避免了开发依赖和构建工具,从而减小了镜像体积。
--from
指令COPY --from=builder
用来从 builder
阶段复制文件到当前阶段。
你可以选择指定从哪个阶段复制文件,只将你需要的文件带入最终镜像。
通过将构建工具(如编译器、开发依赖等)保留在构建阶段,只将最终的应用和运行时依赖复制到生产镜像中,可以显著减少镜像的体积。
例如,在上面的示例中,构建工具和临时文件都不会包含在最终的镜像中,生产镜像仅包含应用代码和生产依赖。
当 Dockerfile 中包含多个阶段时,Docker 会缓存每个阶段的构建结果。如果某个阶段没有变化,Docker 会复用该阶段的缓存,从而避免不必要的重新构建。这使得后续构建更快。
多阶段构建允许将不同的构建步骤分离到不同的阶段中。例如,安装依赖、构建应用、清理临时文件等,可以在不同的阶段进行处理,使 Dockerfile 更加易读和可维护。
每个构建阶段都可以使用不同的基础镜像,使得你可以灵活选择合适的镜像。例如,你可以在构建阶段使用 node:14
镜像,在生产阶段使用更小的 node:14-slim
镜像,确保最终镜像更小。
在多阶段构建中,Docker 会缓存每个构建阶段的结果。如果你在某个阶段没有更改文件,Docker 会重用该阶段的缓存。你可以利用这一点来优化构建过程,尤其是在依赖不经常变化的情况下。
例如,如果你只修改了应用代码,而没有修改 package.json
,Docker 会复用安装依赖的步骤,仅重新构建应用代码部分,从而加速构建过程。
如果你没有修改 package.json
和 package-lock.json
,Docker 会跳过 RUN npm install
阶段,直接使用缓存的 node_modules
,从而加快构建速度。
多阶段构建 通过将构建过程分成多个阶段,只将最终所需的文件复制到最终镜像中,从而减小了 Docker 镜像的大小。
每个阶段可以有不同的基础镜像和构建步骤,可以在构建过程中实现更高效的依赖安装、构建和清理。
通过使用 Docker 的缓存机制,可以加速构建过程,避免重复的安装和构建步骤。
多阶段构建是 Dockerfile 编写中的一项强大工具,可以帮助你构建更加高效、精简且易于维护的 Docker 镜像。