发布于 2026-01-06 5 阅读
0

什么是多阶段 Docker 构建?

什么是多阶段 Docker 构建?

在快节奏的软件开发和部署领域,每一分钟都至关重要。每一秒都对流程优化至关重要,它可以减少构建等待时间或其他滞后步骤所花费的时间。当您使用 Docker 管理软件构建和部署时,您需要确保尽一切可能简化流程,避免开发人员被冗长的构建过程所困扰。这就是 Docker 的多阶段构建功能如此实用的原因。

在软件开发领域,你很快就会发现,做事从来没有唯一正确的方法。相反,通常有很多方法;关键在于找到最适合你的情况和组织的解决方案。同样,在创建容器镜像时,也有许多不同的技术可以尽可能高效地完成。其中一种方法是使用 Docker 的多阶段构建,它可以帮助减小容器的大小。本文将解释什么是多阶段构建,以及它如何帮助你加快开发流程。

Dockerfile

容器允许您将应用程序及其所有必要组件(例如库和其他依赖项)打包在一起,并将其作为一个整体进行分发。整个应用程序可以转换为镜像,并推送到 Docker Hub 等镜像仓库。要创建镜像,您需要一个 Dockerfile。Dockerfile 是一个简单的文本文件,其中包含创建 Docker 镜像所需的所有命令和指令。它以 Docker 指令列表的形式编写。Dockerfile 首先会将另一个文件(称为基础镜像)的内容复制到您的计算机上。之后,您可以根据正在开发的应用程序添加相应的自定义配置。Docker 引擎会读取 Dockerfile,然后按顺序执行其中的指令。Dockerfile 的主要目的是创建一个部署速度尽可能快、依赖项尽可能少的镜像。

Docker 构建

Docker 是一个容器化平台,允许开发者创建可移植的、自包含的容器。Docker 构建过程始于一个镜像,该镜像只是最终镜像的基础层。这意味着该镜像仅包含操作系统以及执行命令所需的其他软件包。下一步是使用来自其他镜像的层或手动安装软件包,向该基础层添加其他层。Dockerfile 详细定义了所有这些步骤,并可通过 `docker build` 命令作为 Docker 构建过程的输入。`docker build` 命令用于根据 Dockerfile 创建镜像。运行 `docker build` 命令时可以添加标签,以指定要创建的镜像版本。

Docker 构建是最简单的单条命令,它可以自动生成一个镜像,其中包含您在 Dockerfile 中指定的所需配置和依赖项。

多阶段 Docker 构建

多阶段 Docker 构建

每个微服务都应该运行在独立的容器中。如果只使用单阶段 Docker 构建,就会错过构建过程中的一些强大功能。另一方面,多阶段 Docker 构建在部署微服务方面比单阶段构建有很多优势。

多阶段构建是一种将 Docker 镜像构建步骤分解为多个阶段的过程。这样,您可以创建仅包含最终应用程序所需功能所必需的依赖项的镜像,从而节省时间和空间。使用多阶段构建,您首先构建一个仅包含构建应用程序所需依赖项的镜像。然后,在镜像构建完成后,您可以添加创建应用程序所需的任何其他层,并配置其以进行部署。通过这种方式,您可以构建仅包含构建应用程序所需代码的镜像。这种方法也常用于优化容器镜像,使其体积更小。

如上所述,多阶段构建允许您创建仅包含构建应用程序所需依赖项的优化 Docker 镜像。结合 Docker 的分层镜像功能,这可以帮助您节省大量空间。多阶段构建过程可以节省 Docker 主机和 Docker 镜像的空间,并加快构建速度。此外,与包含构建应用程序所需的所有代码相比,该过程将快得多。

在 DevOps 领域,创建两个 Dockerfile(一个用于开发,一个用于生产)并不理想,而多阶段 Docker 构建就派上了用场,因为我们可以为所有环境(开发、测试和生产)创建一个优化的 Dockerfile。

多阶段 Docker 构建示例

Java示例:

为了更好地理解多阶段 Docker 构建的概念,让我们考虑一个简单的 Java Hello World 应用程序。

在名为 `<filename>` 的文件中添加以下代码HelloWorld.java

class HelloWorld {
   public static void main(String[] a) {
       System.out.println("Hello world!");
   }
}
Enter fullscreen mode Exit fullscreen mode

然后,创建一个包含以下内容的 Dockerfile:

FROM openjdk:11-jdk
COPY HelloWorld.java .
RUN javac HelloWorld.java
CMD java HelloWorld
Enter fullscreen mode Exit fullscreen mode

使用以下命令构建镜像:
docker build -t helloworld:huge .

让我们修改 Dockerfile,添加以下内容,以展示多阶段 Docker 构建的工作原理。

FROM openjdk:11-jdk AS build
COPY HelloWorld.java .
RUN javac HelloWorld.java

FROM openjdk:11-jre AS run
COPY --from=build HelloWorld.class .
CMD java HelloWorld
Enter fullscreen mode Exit fullscreen mode

使用以下命令构建镜像:

docker build -t helloworld:small .

现在,让我们来比较一下这两张图片。请查看使用以下命令创建的图片:

docker images

Docker镜像

希望您能看出两个镜像的大小差异。这样,您就可以在同一个 Dockerfile 中分离构建环境和运行时环境。COPY --from=build HelloWorld.class .在创建 Dockerfile 时,请使用多阶段 Docker 构建方法,并将构建环境作为依赖项。这将有助于最大限度地减小 Docker 镜像的大小。

Node.js 示例

让我们通过一个简单的Node.js应用程序来学习,该应用程序具有一个简单的Dockerfile。

FROM node:14-alpine
ADD . /app
WORKDIR /app
COPY package.json .
RUN npm install --production
COPY . .
EXPOSE 3002
CMD [ "node", "app.js" ]
Enter fullscreen mode Exit fullscreen mode

让我们使用以下命令构建镜像:
docker build -t [DockerHub username]/image name:tag

使用以下命令将镜像推送到 Docker Hub:
docker push [DockerHub username]/image name:tag

我已将镜像推送到 DockerHub,以下是镜像及其大小信息。

最新示例图片

现在,让我们尝试使用多阶段 Docker 构建的概念,并修改我们现有的 Dockerfile。

FROM node:14-alpine as base
ADD . /app
WORKDIR /app
COPY package.json .
RUN npm install 
FROM alpine:latest
COPY --from=stage1 /app /app
WORKDIR /app
EXPOSE 3002
CMD [ "node", "app.js" ]
Enter fullscreen mode Exit fullscreen mode

让我们使用与上面类似的命令来构建并推送镜像。只需确保给镜像指定一个不同的名称即可。

多阶段示例

现在,比较一下镜像大小。使用常规 Dockerfile 生成的镜像大小为 48.81 MB,而使用多阶段 Docker 构建生成的镜像大小为 7.12 MB。看出区别了吗?使用多阶段 Docker 构建方法生成的镜像更加优化。

另一个例子展示了如何高效地使用多阶段 Docker 构建,那就是当你想要针对不同的环境剖析 Dockerfile 时。

一个标准的 Dockerfile 文件如下所示:

FROM node:14-alpine

WORKDIR /src
COPY package.json package-lock.json /src/
RUN npm install --production

COPY . /src

EXPOSE 3000

CMD ["node", "bin/www"]
Enter fullscreen mode Exit fullscreen mode

我们将根据上面的 Dockerfile 创建 3 个简单的阶段。

  1. 基础阶段:此阶段将与原始 Dockerfile 有一些共同之处。
  2. 生产阶段:此阶段将包含对生产环境有用的物品
  3. 开发阶段:此阶段将包含对开发环境有用的组件

修改后的Dockerfile如下所示:

FROM node:14-alpine as base

WORKDIR /src
COPY package.json package-lock.json /src/
EXPOSE 3000

FROM base as production
ENV NODE_ENV=production
RUN npm ci
COPY . /src
CMD ["node", "bin/www"]

FROM base as dev
ENV NODE_ENV=development
RUN npm install -g nodemon && npm install
COPY . /src
CMD ["nodemon", "bin/www"]
Enter fullscreen mode Exit fullscreen mode

多阶段构建的一些显著优势:

  • 优化 Docker 镜像的整体大小
  • 免去了为不同阶段创建多个 Dockerfile 的麻烦。
  • 易于调试特定构建阶段
  • 能够在新的环境中将前一阶段作为新阶段使用
  • 能够利用缓存图像来加快整个处理过程
  • 通过多阶段构建,随着镜像尺寸的减小,可以降低发现漏洞的风险。

使用 Harness 部署应用程序

注册Harness免费试用版,并选择“TryNextGen”选项卡,即可获得流畅体验。创建一个新项目,然后选择“持续交付”模块。开始创建新的流水线,并添加流水线所需的所有详细信息。

安全平台

选择阶段

注意:要使 Harness 发挥作用,需要在 Kubernetes 集群上运行一个名为“Delegate”的程序。

什么是 Harness Delegate?
Harness Delegate 是一种服务/软件,您需要在目标集群(在本例中为 Kubernetes 集群)上安装/运行它,以便将您的工件、基础设施、协作、验证和其他提供程序与 Harness Manager 连接起来。首次设置 Harness 时,您需要安装 Harness Delegate。

本文不会深入探讨 Delegate,因为它本身就可以单独写一篇博客文章。目前,您只需知道 Delegate 会为您执行所有部署操作。如果您想了解更多关于 Delegate 的信息,可以点击此处阅读。

光盘开始

接下来,请为您的应用程序指定服务、基础架构和部署策略。一切设置完毕后,保存配置并运行以部署应用程序。

CD快速入门

好了!流水线成功运行后,您应该能在指定的 Kubernetes 集群上看到您的应用程序已部署。您可以使用 kubectl 命令“kubectl get pods”进行验证。您想试用 Harness CD 吗?注册Harness CD 免费试用版吧!

结论

多阶段构建有助于构建可在任何地方运行的优化 Docker 镜像。如果您希望简化软件交付流程,那么您绝对应该了解多阶段 Docker 构建的工作原理。这种方法可以加快软件部署速度,并且镜像可以重复使用,从而节省时间和精力。多阶段构建是简化镜像创建流程并节省开发人员时间的绝佳方式。

在云原生环境中,安全性至关重要。多阶段 Docker 构建的一大优势在于,它可以减少镜像中的依赖项和不必要的软件包,从而缩小攻击面。此外,它还能保持镜像的简洁和精简,只包含运行生产环境应用程序所需的组件。否则,我们最终都会构建并推送体积庞大且漏洞百出的镜像,这些漏洞可能为攻击者提供入侵应用程序的便捷途径。尝试使用多阶段 Docker 构建来优化镜像并提升安全性。希望本文能帮助您更好地了解多阶段 Docker 构建及其优势。

文章来源:https://dev.to/pavanbelagatti/what-are-multi-stage-docker-builds-1mi9