详解SpringBoot23应用制作Docker镜像官方方案

28次阅读

共计 4014 个字符,预计需要花费 11 分钟才能阅读完成。

关于《SpringBoot-2.3 容器化技术》系列

《SpringBoot-2.3 容器化技术》系列,旨在和大家一起学习实践 2.3 版本带来的最新容器化技术,让咱们的 Java 应用更加适应容器化环境,在云计算时代依旧紧跟主流,保持竞争力;

全系列文章分为主题和辅助两部分,主题部分如下:

  1. 《体验 SpringBoot(2.3) 应用制作 Docker 镜像 (官方方案)》;
  2. 《详解 SpringBoot(2.3) 应用制作 Docker 镜像 (官方方案)》;
  3. 《掌握 SpringBoot-2.3 的容器探针:基础篇》;
  4. 《掌握 SpringBoot-2.3 的容器探针:深入篇》;
  5. 《掌握 SpringBoot-2.3 的容器探针:实战篇》;

辅助部分是一些参考资料和备忘总结,如下:

  1. 《SpringBoot-2.3 镜像方案为什么要做多个 layer》;
  2. 《设置非 root 账号不用 sudo 直接执行 docker 命令》;
  3. 《开发阶段,将 SpringBoot 应用快速部署到 K8S》;

本篇简介

在前文,咱们快速体验了官方推荐的 docker 镜像制作方案,但也产生了几个疑问:

  1. SpringBoot-2.3 版本推荐的镜像构建方案和旧版本比有什么不同?
  2. pom.xml 中 <font color=”blue”>spring-boot-maven-plugin</font> 插件新增的参数,到底做了什么?
  3. Dockerfile 中,<font color=”blue”>java -Djarmode=layertools -jar application.jar extract</font> 这个操作啥意思?

本篇的目标就是解答上述问题,在寻找答案的过程中不断补全知识点,提升自己;

关键知识点:镜像 layer

前文多次提到的镜像 layer 到底是什么,为什么会有多层 layer?有必要先把这个知识点夯实了,请参考文章《SpringBoot-2.3 镜像方案为什么要做多个 layer》

老版本 SpringBoot 的官方方案

以 <font color=”blue”>SpringBoot-2.2.0.RELEASE</font> 版本为例,官方文档 (
https://docs.spring.io/spring…:

  1. 将 SpringBoot 工程编译构建,在 target 目录得到 jar;
  2. 在 target 目录新建 dependency 文件夹;
  3. 将 jar 解压到 dependency 文件夹;
  4. 编写 Dockerfile 文件,内容如下:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.MyApplication"]
  1. 可见,官方推荐的做法是将整个 jar 文件解压,在 Dockerfile 中多次用 COPY 命令分别复制,这样做的好处显而易见:多个 layer,如果镜像的新版本中只修改了应用代码,那么下载镜像时只会下载 /app 这个 layer,其他部分直接使用本地缓存,这是 docker 镜像的常规优化手段;
  2. 上述方案有个小问题:<font color=”red”> 麻烦!!!</font>
  3. 于是 2.3.0.RELEASE 版本做了些优化,让事情变得简单些;

2.3.0.RELEASE 版本方案和旧版的区别

2.3.0.RELEASE 版本构建 Docker 的步骤如下:

  1. pom.xml 中的 spring-boot-maven-plugin 插件增加一个配置项;

2. 编译构建生成 jar;

  1. 编写 Dockerfile,里面用到了多阶段构建 (multi-stage builds),用工具从 jar 中提取拆分后,再多次执行 COPY 命令将拆分后的内容放入镜像,达到多个 layer 的目的;

因此,2.3.0.RELEASE 版本和旧版本相比有如下变化:

  1. <font color=”blue”>pom.xml</font> 中多了个参数;
  2. 构建好 jar 后,无需自己解压 jar;
  3. Dockefile 内容不一样,旧版是手动解压 jar,再在 Dockerfile 分别复制,2.3.0.RELEASE 是通过 <font color=”red”>java 命令从 jar 中提取出各部分内容 </font>;

搞清楚了新旧版本的区别,咱们继续研究下一个问题吧;

pom.xml 中 spring-boot-maven-plugin 插件新增的参数

  1. pring-boot-maven-plugin 插件新增参数如下图所示:

  1. 上述参数有啥用?我这边编译构建了两次 jar,第一次有上述参数,第二次没有,将两次生成的 jar 解压后对比,发现用了上述参数后,生成的 jar 会多出下图红框中的两个文件:

  1. 看看 <font color=”blue”>layers.idx</font> 文件的内容,如下图:

  1. 上图中的内容分别是什么意思呢?官方已给出了详细解释,如下图红框:

  1. 综上所述,layers.idx 文件是个清单,里面记录了所有要被复制到镜像中的信息,接下来看看如何使用 layers.idx 文件,这就涉及到 jar 包中新增的另一个文件:<font color=”blue”>spring-boot-jarmode-layertools-2.3.0.RELEASE.jar</font>

spring-boot-jarmode-layertools 工具

  1. 前面已经介绍过 jar 中除了 layers.idx,还多了个文件:<font color=”blue”>spring-boot-jarmode-layertools-2.3.0.RELEASE.jar</font>,来看看这个文件的用处;
  2. 进入工程的 <font color=”blue”>target</font> 目录,这里面是编译后的 jar 文件 (我这里文件名为 dockerlayerdemo-0.0.1-SNAPSHOT.jar),注意此时的 <font color=”blue”>spring-boot-maven-plugin</font> 插件是带上了下图红框中的参数的:

  1. 执行以下命令:
java -Djarmode=layertools -jar dockerlayerdemo-0.0.1-SNAPSHOT.jar list
  1. 得到结果如下图所示,是 layers.idx 文件的内容:

  1. 来看看官方对这个 <font color=”blue”>layertools</font> 的解释,list 参数的作用上面我们已经体验过了,重点是红框中的 <font color=”red”>extract</font> 参数,它的作用是从 jar 中提取构建镜像所需的内容:

  1. 看到这里,您是否想到了《体验 SpringBoot(2.3) 应用制作 Docker 镜像 (官方方案)》中 Dockerfile 的内容,请看下图的红框和红字,是否有种恍然大悟的感觉:jar 构建生成清单 layers.idx,Dockerfile 中根据清单从 jar 提取文件放入镜像:

至此,三个问题都已经找到了答案,小结一下:

SpringBoot-2.3.0.RELEASE 推荐的镜像构建方案和旧版本相比有什么不同

  1. pom.xml 中的 spring-boot-maven-plugin 插件增加一个配置项;
  2. 构建好 jar 后,旧版本要自己解压 jar,新版不需要;
  3. 新版本的 jar 中,多了个文件清单 <font color=”blue”>layers.idx</font> 和镜像文件处理工具 <font color=”blue”>spring-boot-jarmode-layertools-2.3.0.RELEASE.jar</font>;
  4. 旧版的 Dockefile 内容:因为前面解压好了,所有在 Dockerfile 里直接复制前面解压的内容,这里就有个风险:前一步解压和当前复制的文件位置要保证一致;
  5. 新版的 Dockerfile 内容:使用工具 spring-boot-jarmode-layertools-2.3.0.RELEASE.jar,根据的 layers.idx 内容从 jar 中提取文件,复制到镜像中;
  6. 新版的 Dockerfile 中,由于使用了分阶段构建,因此从 jar 提取文件的操作不会保存到镜像的 layer 中;

pom.xml 中 spring-boot-maven-plugin 插件新增的参数,到底做了什么

spring-boot-maven-plugin 插件新增的参数,使得编译构建得到 jar 中多了两个文件,如下图所示:

Dockerfile 中,java -Djarmode=layertools -jar application.jar extract 这个操作啥意思

  1. <font color=”blue”>java -Djarmode=layertools -jar application.jar extract</font> 的作用是从 jar 中提取文件,这些文件是 docker 镜像的一部分;
  2. 上述操作的参数是 <font color=”blue”>extract</font>,另外还有两个参数,官方解释它们的作用如下:

至此,问题已全部澄清,相信您对 SpringBoot-2.3.0.RELEASE 官方的镜像构建方案也足够了解了,最后是我根据自己的认识画的流程图,帮助您快速理解整个构建流程:

欢迎访问我的 GitHub

  • 地址:https://github.com/zq2599/blog_demos
  • 内容:原创文章分类汇总,及配套源码,涉及 Java、Docker、K8S、DevOPS 等

欢迎关注我的公众号:程序员欣宸

https://github.com/zq2599/blog_demos

正文完
 0