如何使用多阶段 Dockerfile 进行 Java EE 应用程序打包

DockerDockerBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

Docker 的多阶段 Dockerfile 为简化 Java EE 应用程序的打包过程提供了一个强大的解决方案。本教程将指导你完成使用多阶段 Dockerfile 构建和优化 Java EE 应用程序的步骤,确保高效的部署和分发。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/images("List Images") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/run -.-> lab-411621{{"如何使用多阶段 Dockerfile 进行 Java EE 应用程序打包"}} docker/inspect -.-> lab-411621{{"如何使用多阶段 Dockerfile 进行 Java EE 应用程序打包"}} docker/create -.-> lab-411621{{"如何使用多阶段 Dockerfile 进行 Java EE 应用程序打包"}} docker/images -.-> lab-411621{{"如何使用多阶段 Dockerfile 进行 Java EE 应用程序打包"}} docker/build -.-> lab-411621{{"如何使用多阶段 Dockerfile 进行 Java EE 应用程序打包"}} end

理解多阶段 Dockerfile

多阶段 Dockerfile 是 Docker 17.05 中引入的一项强大功能,它允许你通过在单个 Dockerfile 中使用多个阶段来创建优化的 Docker 镜像。这种方法有助于通过将构建环境与运行时环境分离来减小最终镜像的大小,并改进构建过程。

什么是多阶段 Dockerfile?

多阶段 Dockerfile 是一个包含多个 FROM 语句的 Dockerfile,每个语句代表构建过程中的一个不同阶段。每个阶段可以使用不同的基础镜像,最后一个阶段用于创建最终的 Docker 镜像。

graph TD A[基础镜像] --> B[构建阶段] B --> C[运行时阶段] C --> D[最终镜像]

使用多阶段 Dockerfile 的好处

  1. 减小镜像大小:通过将构建环境与运行时环境分离,你可以创建一个更小的最终 Docker 镜像,该镜像仅包含应用程序运行所需的必要组件。
  2. 改进构建过程:多阶段 Dockerfile 可以通过允许你在不同阶段使用不同的基础镜像来简化构建过程,减少对复杂构建脚本或单独 Dockerfile 的需求。
  3. 增强安全性:通过减小最终镜像的大小,你可以最小化攻击面并降低安全漏洞的风险。

如何使用多阶段 Dockerfile

要使用多阶段 Dockerfile,你需要在 Dockerfile 中定义多个 FROM 语句,每个语句代表一个不同的阶段。最后一个阶段用于创建最终的 Docker 镜像。

## 构建阶段
FROM maven:3.8.2-openjdk-11 AS build
COPY. /app
WORKDIR /app
RUN mvn clean package

## 运行时阶段
FROM openjdk:11-jdk-slim
COPY --from=build /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

在这个例子中,第一个阶段使用 maven:3.8.2-openjdk-11 镜像来构建 Java EE 应用程序,第二个阶段使用 openjdk:11-jdk-slim 镜像来创建最终的 Docker 镜像,该镜像仅包含必要的运行时组件。

使用多阶段 Dockerfile 构建 Java EE 应用程序

在本节中,我们将逐步介绍使用多阶段 Dockerfile 构建 Java EE 应用程序的过程。

准备 Java EE 应用程序

假设你有一个想要使用多阶段 Dockerfile 进行打包的 Java EE 应用程序。该应用程序的结构如下:

my-java-ee-app/
├── pom.xml
└── src/
    ├── main/
    │   ├── java/
    │   │   └── com/
    │   │       └── example/
    │   │           └── MyApp.java
    │   └── webapp/
    │       └── WEB-INF/
    │           └── web.xml
    └── test/
        └── java/
            └── com/
                └── example/
                    └── MyAppTest.java

创建多阶段 Dockerfile

以下是一个用于构建和打包 Java EE 应用程序的多阶段 Dockerfile 示例:

## 构建阶段
FROM maven:3.8.2-openjdk-11 AS build
COPY. /app
WORKDIR /app
RUN mvn clean package

## 运行时阶段
FROM tomcat:9.0-jdk11-openjdk-slim
COPY --from=build /app/target/*.war /usr/local/tomcat/webapps/app.war

在这个 Dockerfile 中,我们有两个阶段:

  1. 构建阶段:此阶段使用 maven:3.8.2-openjdk-11 镜像来构建 Java EE 应用程序。COPYRUN 命令用于复制应用程序源代码并使用 Maven 构建应用程序。
  2. 运行时阶段:此阶段使用 tomcat:9.0-jdk11-openjdk-slim 镜像作为基础镜像。COPY --from=build 命令用于将上一阶段构建的 WAR 文件复制到 Tomcat 的 webapps 目录中。

构建并运行 Docker 镜像

要构建 Docker 镜像,请在包含 Dockerfile 的目录中运行以下命令:

docker build -t my-java-ee-app.

镜像构建完成后,你可以运行容器:

docker run -p 8080:8080 my-java-ee-app

这将启动 Tomcat 服务器并部署 Java EE 应用程序。然后,你可以通过 http://localhost:8080/app 访问该应用程序。

为 Java EE 应用优化多阶段 Dockerfile

在使用多阶段 Dockerfile 构建 Java EE 应用程序时,可以采用多种优化技术来进一步减小最终 Docker 镜像的大小并改进构建过程。

利用构建依赖项

一种常见的优化方法是仅在构建阶段利用构建依赖项,并将它们排除在最终的运行时阶段之外。例如,你可以使用一个单独的构建镜像,该镜像包含所有必要的构建工具,如 Maven 或 Gradle 镜像,然后将构建好的工件复制到一个更小的运行时镜像中。

## 构建阶段
FROM maven:3.8.2-openjdk-11 AS build
COPY. /app
WORKDIR /app
RUN mvn clean package

## 运行时阶段
FROM openjdk:11-jdk-slim
COPY --from=build /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

利用多阶段缓存

Docker 的多阶段构建功能还允许你利用构建缓存来加速后续构建。通过以最大化缓存重用的方式组织你的 Dockerfile,可以显著减少构建时间。

## 基础阶段
FROM maven:3.8.2-openjdk-11 AS base
WORKDIR /app

## 复制依赖项
COPY pom.xml.
RUN mvn dependency:go-offline

## 构建阶段
FROM base AS build
COPY..
RUN mvn clean package

## 运行时阶段
FROM openjdk:11-jdk-slim
COPY --from=build /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

在这个例子中,pom.xml 文件在基础阶段被复制,并且依赖项被下载。这确保了依赖项解析步骤被缓存,从而加速后续构建。

优化运行时镜像

另一种优化技术是在运行时阶段使用更小的基础镜像。例如,你可以使用 openjdk:11-jdk-slim 镜像而不是完整的 openjdk:11-jdk 镜像,这可以显著减小最终镜像的大小。

## 运行时阶段
FROM openjdk:11-jdk-slim
COPY --from=build /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

此外,你可以使用多阶段构建、基于 Alpine 的镜像或无发行版镜像等技术来进一步优化运行时镜像的大小。

通过应用这些优化技术,你可以为你的 Java EE 应用程序创建高度优化的 Docker 镜像,减小镜像大小并改进构建过程。

总结

在本教程结束时,你将对如何利用多阶段 Dockerfile 有效地打包你的 Java EE 应用程序有扎实的理解。你将学习优化构建过程、减小镜像大小以及使用 Docker 创建可靠且可重复的部署管道的技术。这些知识将使你能够提高 Java EE 应用程序部署的效率和可扩展性。