您已经创建了一个 Spring Boot 应用程序。它在您的本地计算机上运行良好,现在您需要将该应用程序部署到其他地方。在某些平台上,您可以直接提交jar文件,它将被部署。在某些地方,您可以启动虚拟机,下载源代码,构建并运行它。但是,大多数时候您需要使用容器来部署应用程序。大多数时候,Docker 用于在容器中构建和运行镜像。此外,当您将 jar 文件上传到某些平台时,应用程序会在后台的容器内运行。
因此,在本博客中,我们将看到 3 种不同的方法来为给定的 Spring Boot 应用程序构建 Docker 映像。让我们开始吧:
为任何应用程序构建 Docker 映像的简单且不充分的方法是使用一个简单的 Dockerfile,该文件将 jar 文件复制到映像中并使用 java -jar 命令运行它。
这是 Dockerfile,您可以将其放在项目的根目录中:
FROM eclipse-temurin:21-jre-ubi9-minimal ARG JAR_FILE COPY ${JAR_FILE} application.jar ENTRYPOINT ["java", "-jar", "/application.jar"]
我们指定了一个参数 JAR_FILE,它是要使用的 jar 文件的位置。
创建上述 Dockerfile 后,使用以下步骤创建 Docker 镜像:
为 Spring Boot 项目构建 jar 文件:
./gradlew bootJar # For Gradle build system
或者
./mvnw spring-boot:build-jar # For Maven build system
使用 Dockerfile 使用最新的 jar 文件构建 Docker 镜像。在以下命令中,将 {IMAGE_NAME} 替换为所需的映像名称,将 {JAR_FILE} 替换为生成的 jar 文件的路径。图像名称还包含一个标签,例如 - mycompany/product-service:0.0.1-SNAPSHOT:
docker build --build-arg JAR_FILE={JAR_FILE} --tag {IMAGE_NAME} .
验证 Docker 镜像是否是使用以下命令构建的。您应该能够看到上面命令中指定名称的图像:
docker images
虽然可以轻松地将 Spring Boot uber jar 打包为 Docker 镜像(如前面的方法中所述),但在 Docker 镜像中按原样复制和运行 fat jar 有很多缺点。例如,
由于我们编译代码的频率比升级 Spring Boot 版本的频率高,因此最好将各个部分分开一些。如果我们将那些很少更改的jar文件放在应用层之前的层中,那么Docker通常只需要更改底层,并且可以从其缓存中选取其余的。
要创建分层 Docker 镜像,我们需要首先创建分层 jar。如今,它在 Gradle 和 Maven 中默认启用。您可以使用以下设置启用或禁用分层 jar 行为:
// build.gradle tasks.named("bootJar") { layered { enabled = false } }
// build.gradle.kts tasks.named<BootJar>("bootJar") { layered { enabled.set(false) } }
<!-- pom.xml --> <project> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layers> <enabled>true</enabled> </layers> </configuration> </plugin> </plugins> </build> </project>
您甚至可以调整图层的创建方式。请参阅 gradle 或 maven 配置的文档。
下面是 Dockerfile,可用于利用分层 jar 并创建 Spring Boot 应用程序的分层 Docker 映像。
# Perform the extraction in a separate builder container FROM eclipse-temurin:21-jre-ubi9-minimal AS builder WORKDIR /builder # This points to the built jar file in the target folder # Adjust this to 'build/libs/*.jar' if you're using Gradle ARG JAR_FILE=target/*.jar # Copy the jar file to the working directory and rename it to application.jar COPY ${JAR_FILE} application.jar # Extract the jar file using an efficient layout RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted # This is the runtime container FROM eclipse-temurin:21-jre-ubi9-minimal WORKDIR /application # Copy the extracted jar contents from the builder container into the working directory in the runtime container # Every copy step creates a new docker layer # This allows docker to only pull the changes it really needs COPY --from=builder /builder/extracted/dependencies/ ./ COPY --from=builder /builder/extracted/spring-boot-loader/ ./ COPY --from=builder /builder/extracted/snapshot-dependencies/ ./ COPY --from=builder /builder/extracted/application/ ./ # Start the application jar - this is not the uber jar used by the builder # This jar only contains application code and references to the extracted jar files # This layout is efficient to start up and CDS friendly ENTRYPOINT ["java", "-jar", "application.jar"]
构建分层 Docker 镜像的步骤与构建基本 Docker 镜像相同。请参考那里。
如果我告诉你无需创建 Dockerfile 就可以创建 Docker 镜像,你会怎样?我们可以使用 Cloud Native Buildpacks 直接从 Gralde 或 Maven 插件构建 docker 镜像。一些平台(如 Heroku 或 Cloud Foundry)使用 Buildpack 将提供的 jar 文件转换为可运行的映像。
Spring Boot 包括直接对 Maven 和 Gradle 的构建包支持。我们不需要包含任何额外的插件。只需运行以下命令:
./gradlew bootBuildImage # For gradle build system
或者
./mvnw spring-boot:build-image # For maven build system
上述命令生成默认名称为 {PROJECT_NAME}:${PROJECT_VERSION} 的图像。如果你想配置生成图片的名称,可以按照以下步骤操作:
我们可以配置 bootBuildImage 任务来设置镜像的名称,如下所示:
// For build.gradle.kts val imagePrefix = "javarush" val dockerImageName = "docker-example" tasks.named<BootBuildImage>("bootBuildImage") { imageName.set("${imagePrefix}/${dockerImageName}:${version}") }
// For build.gradle def imagePrefix = "javarush" def dockerImageName = "docker-example" tasks.named("bootBuildImage") { imageName = "${imagePrefix}/${dockerImageName}:${version}" }
我们可以配置 spring-boot-maven-plugin 使用其他镜像名称,如下所示:
<properties> <imagePrefix>javarush</imagePrefix> </properties> ... <project> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <image> <name>${imagePrefix}/${project.artifactId}:${project.version}</name> </image> </configuration> </plugin> </plugins> </build> </project>
我们甚至可以在运行构建镜像的命令时定义镜像的名称。
./gradlew bootBuildImage --imageName=javarush/docker-example:1.0.0 # For grade build system ./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=javarush/docker-example:1.0.0 # For maven build system
You can see the documentation to further configure Gradle or Maven plugin.
This is my go-to method to create a Docker image for any Spring Boot application.
Once you create a docker image, you need to make sure that it works as expected. After you make sure that the image is created, you can directly run it using the docker run command. For example,
docker run -p "8080:8080" {IMAGE_NAME}
But, this is not how images are used in production applications. Docker Compose is used to run and manage multiple docker images.
In this blog, we have seen how to build Docker images for Spring Boot applications using different methods. Being able to build docker images for your apps is a must skill to know because the image is what gets delivered. Thanks for reading the article till the end. I appreciate it. I will meet you in the next one. As always, all feedback and suggestions are welcome.
以上是使用 Buildpack 创建 Spring Boot 应用程序的 Docker 映像的详细内容。更多信息请关注PHP中文网其他相关文章!