当前位置:首页 >热点 >撸一撸,Spring Boot 构建Docker镜像! 撸一撸Spring Boot 构建Docker镜像

撸一撸,Spring Boot 构建Docker镜像! 撸一撸Spring Boot 构建Docker镜像

2024-06-28 11:19:14 [百科] 来源:避面尹邢网

撸一撸,撸一撸Spring Boot 构建Docker镜像!构建

作者:刘一手 开源 随着越来越多的镜像组织转向容器和虚拟服务器,Docker正成为软件开发工作流程中一个更重要的撸一撸部分。为此,构建Spring Boot 2.3中最新的镜像功能之中,提供了为Spring Boot应用程序创建 Docker 镜像的撸一撸能力。

[[351755]]

随着越来越多的构建组织转向容器和虚拟服务器,Docker正成为软件开发工作流程中一个更重要的镜像部分。为此,撸一撸Spring Boot 2.3中最新的构建功能之中,提供了为Spring Boot应用程序创建 Docker 镜像的镜像能力。

撸一撸,Spring Boot 构建Docker镜像! 撸一撸Spring Boot 构建Docker镜像

这篇文章的撸一撸目的,就是构建为了给大家介绍如何为 Spring Boot 应用程序创建 Docker 镜像。

撸一撸,Spring Boot 构建Docker镜像! 撸一撸Spring Boot 构建Docker镜像

1. 传统Docker构建

撸一撸,Spring Boot 构建Docker镜像! 撸一撸Spring Boot 构建Docker镜像

使用Spring Boot 构建 Docker 镜像的镜像传统方法是使用 Dockerfile 。下面是一个简单的例子:

  1. FROM openjdk:8-jdk-alpine 
  2. EXPOSE 8080 
  3. ARG JAR_FILE=target/demo-app-1.0.0.jar 
  4. ADD ${ JAR_FILE} app.jar 
  5. ENTRYPOINT ["java","-jar","/app.jar"] 

然后我们可以使用 docker build 命令来创建 Docker 映像。这对大多数应用程序都很好,但也有一些缺点。

首先,我们使用的是 Spring Boot 创建的 fat jar。这会影响启动时间,尤其是在集装箱环境中。我们可以通过添加jar文件的分解内容来节省启动时间。

其次,Docker镜像是分层构建的。Spring Boot fat jar 的特性使得所有的应用程序代码和第三方库都放在一个层中。这意味着即使只有一行代码更改,也必须重新构建整个层。

通过在构建之前分解 jar ,应用程序代码和第三方库各自获得自己的层。这样,我们便可以利用Docker的缓存机制。现在,当某一行代码被更改时,只需要重新构建相应的层。

考虑到这一点,让我们看看Spring Boot 如何改进创建Docker镜像的过程。

2. Buildpacks

BuildPacks 是一种提供框架和应用程序依赖性的工具。

例如,给定一个Spring Boot fat jar,一个buildpack将为我们提供Java运行时。这使我们可以跳过 Dockerfile 并自动获得一个合理的docker 镜像。

Spring Boot 包括对 bulidpacks 的Maven和Gradle支持。例如,使用Maven构建时,我们将运行以下命令:

  1. ./mvnw spring-boot:build-image 

我们观察下一些相关的输出,看看发生了什么:

  1. [INFO] Building jar: target/demo-0.0.1-SNAPSHOT.jar 
  2. ... 
  3. [INFO] Building image 'docker.io/library/demo:0.0.1-SNAPSHOT' 
  4. ... 
  5. [INFO]  > Pulling builder image 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 100% 
  6. ... 
  7. [INFO]     [creator]     ===> DETECTING 
  8. [INFO]     [creator]     5 of 15 buildpacks participating 
  9. [INFO]     [creator]     paketo-buildpacks/bellsoft-liberica 2.8.1 
  10. [INFO]     [creator]     paketo-buildpacks/executable-jar    1.2.8 
  11. [INFO]     [creator]     paketo-buildpacks/apache-tomcat     1.3.1 
  12. [INFO]     [creator]     paketo-buildpacks/dist-zip          1.3.6 
  13. [INFO]     [creator]     paketo-buildpacks/spring-boot       1.9.1 
  14. ... 
  15. [INFO] Successfully built image 'docker.io/library/demo:0.0.1-SNAPSHOT' 
  16. [INFO] Total time:  44.796 s 

第一行显示我们构建了标准的 fat jar,与其他典型的maven包一样。

下一行开始Docker映像构建。然后,看到这个 bulid 拉取了 packeto 构建器。

packeto 是基于云原生 bulidpacks 的实现。它负责分析我们的项目并确定所需的框架和库。在我们的例子中,它确定我们有一个Spring Boot项目并添加所需的构建包。

最后,我们看到生成的Docker映像和总构建时间。注意,在第一次构建时,花了相当多的时间下载构建包并创建不同的层。

buildpacks 的一大特点是Docker映像是多层的。因此,如果我们只更改应用程序代码,后续构建将更快:

  1. ... 
  2. [INFO]     [creator]     Reusing layer 'paketo-buildpacks/executable-jar:class-path' 
  3. [INFO]     [creator]     Reusing layer 'paketo-buildpacks/spring-boot:web-application-type' 
  4. ... 
  5. [INFO] Successfully built image 'docker.io/library/demo:0.0.1-SNAPSHOT' 
  6. ... 
  7. [INFO] Total time:  10.591 s 

3. 层级jar包

在某些情况下,我们可能不喜欢使用 bulidpacks ——也许我们的基础架构已经绑定到另一个工具上,或者我们已经有了我们想要重新使用的自定义 Dockerfiles 。

基于这些原因,Spring Boot 还支持使用分层jars 构建Docker映像。为了了解它的工作原理,让我们看看一个典型的Spring Boot fat jar 布局:

  1. org/ 
  2.   springframework/ 
  3.     boot/ 
  4.   loader/ 
  5. ... 
  6. BOOT-INF/ 
  7.   classes/ 
  8. ... 
  9. lib/ 
  10. ... 

fat jar 由3个主要区域组成:

  • 启动Spring应用程序所需的引导类
  • 应用程序代码
  • 第三方库

使用分层jar,结构看起来很相似,但是我们得到了一个新的 layers.idx 将 fat jar 中的每个目录映射到一个层的文件:

  1. - "dependencies": 
  2.   - "BOOT-INF/lib/" 
  3. - "spring-boot-loader": 
  4.   - "org/" 
  5. - "snapshot-dependencies": 
  6. - "application": 
  7.   - "BOOT-INF/classes/" 
  8.   - "BOOT-INF/classpath.idx" 
  9.   - "BOOT-INF/layers.idx" 
  10.   - "META-INF/" 

Out-of-the-box, Spring Boot provides four layers:

开箱即用,Spring Boot 提供4层:

  • dependencies: 来自第三方的依赖
  • snapshot-dependencies: 来自第三方的 snapshot 依赖
  • resources: 静态资源
  • application: 应用程序代码和资源(resources)

我们的目标是将应用程序代码和第三方库放置到层中,以反映它们更改的频率。

例如,应用程序代码可能是更改最频繁的代码,因此它有自己的层。此外,每一层都可以独立演化,只有当一层发生变化时,才会为它重建 Docker 镜像。

现在我们了解了分层 jar 结构,接下来看看如何利用它来制作 Docker 映像。

3.1.创建分层 jar

首先,我们必须建立一个项目来创建一个分层的jar。对于Maven,则需要在POM的 Spring Boot plugin 部分添加一个新的配置:

  1. <plugin> 
  2.     <groupId>org.springframework.boot</groupId> 
  3.     <artifactId>spring-boot-maven-plugin</artifactId> 
  4.     <configuration> 
  5.         <layers> 
  6.             <enabled>true</enabled> 
  7.         </layers> 
  8.     </configuration> 
  9. </plugin> 

有了这个配置,Maven package 命令(包括它的其他依赖命令)将使用前面提到的四个默认层生成一个新的分层jar。

3.2. 查看和提取分层

下一步,我们需要从 jar 中提取层,这样Docker镜像才能拥有正确的层。要检查分层jar的任何层,可以运行以下命令:

  1. java -Djarmode=layertools -jar demo-0.0.1.jar list 

然后提取它们,运行命令:

  1. java -Djarmode=layertools -jar demo-0.0.1.jar extract 

3.3. 创建Docker映像

将这些层合并到 Docker 映像中的最简单方法是使用 Dockerfile :

  1. FROM adoptopenjdk:11-jre-hotspot as builder 
  2. ARG JAR_FILE=target/*.jar 
  3. COPY ${ JAR_FILE} application.jar 
  4. RUN java -Djarmode=layertools -jar application.jar extract 
  5.   
  6. FROM adoptopenjdk:11-jre-hotspot 
  7. COPY --from=builder dependencies/ ./ 
  8. COPY --from=builder snapshot-dependencies/ ./ 
  9. COPY --from=builder spring-boot-loader/ ./ 
  10. COPY --from=builder application/ ./ 
  11. ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] 

这个 Dockerfile 从fat jar中提取层,然后将每个层复制到Docker映像中。

每个COPY指令最终都会在Docker映像中生成一个新层。

如果我们构建这个Dockerfile,我们可以看到分层jar中的每个层都作为自己的层添加到Docker镜像中:

  1. ... 
  2. Step 6/10 : COPY --from=builder dependencies/ ./ 
  3.  ---> 2c631b8f9993 
  4. Step 7/10 : COPY --from=builder snapshot-dependencies/ ./ 
  5.  ---> 26e8ceb86b7d 
  6. Step 8/10 : COPY --from=builder spring-boot-loader/ ./ 
  7.  ---> 6dd9eaddad7f 
  8. Step 9/10 : COPY --from=builder application/ ./ 
  9.  ---> dc80cc00a655 
  10. ... 

在本文中,我们学习了使用 Spring Boot 构建 Docker 映像的各种方法。

使用 buildpacks,我们可以获得合适的Docker镜像,而无需模板或自定义配置。

或者,再多花点功夫,我们就可以使用分层 jar 来获得一个更加定制的Docker镜像。

本文转载自微信公众号「锅外的大佬」,可以通过以下二维码关注。转载本文请联系锅外的大佬公众号。

 

责任编辑:武晓燕 来源: 锅外的大佬 DockerSpring Boot应用

(责任编辑:综合)

    推荐文章
    热点阅读