Springboot框架是这样提高创建 docker 容器的效率的,一文带你读懂

前言

小伙伴们好呀,今天来和大家聊聊这个 Springboot 在为创建高效容器方面中做的一个改动

当然,写这篇文章也不是因为实际项目真的需要我去研究这东西,而是我在上篇文章

《为什么SpringBoot可以直接运行 jar 包?》 中留了坑🕳 ,还有错误得纠正🐖 (原文也稍微改了下,但是只能改20字🙃)

这里应该改为

jarmodeextract 参数会自动将 jar 包中的文件按 layers.idx 中的分层提取出来。

img

改进原因

There’s always a certain amount of overhead when running a fat jar without unpacking it, and in a containerized environment this can be noticeable.

The other issue is that putting your application’s code and all its dependencies in one layer in the Docker image is sub-optimal.

上面这两句摘自 Springboot2.4.13 官方文档,但是这个改动是 2.3 就有了的(看了下 2.3 的,也还是这几句话🐷)

https://docs.spring.io/spring-boot/docs/2.4.13/reference/html/spring-boot-features.html#boot-features-container-images

大意就是说,

  1. 在容器中,如果没有解压就直接运行一个 jar 包,它带来的开销是明显的
  2. 将 应用代码和包依赖都混在同一层,也是可以被优化的地方。

w(゚Д゚)w ,感觉说的很有道理 哈哈哈

img

默默三连认同

但是这里有个疑问,那之前 2.3 之前是怎么解决这个问题的呢?还是说现在才解决的呢?🤔

求证

怀着严谨求证的态度,我打开了 Springboot2.2.9 的版本 👇

https://docs.spring.io/spring-boot/docs/2.2.9.RELEASE/reference/htmlsingle/#containers-deployment

可以看到这里列举了不高效的写法,以及推荐写法

img

这里我将 Springboot2.2.9 版本中 创建高效容器 的 Dockerfile 抄下来

FROM openjdk:8-jdk-alpine AS builder



WORKDIR target/dependency



ARG APPJAR=target/*.jar



COPY ${APPJAR} app.jar



RUN jar -xf ./app.jar



 



FROM openjdk:8-jre-alpine



VOLUME /tmp



ARG DEPENDENCY=target/dependency



COPY --from=builder ${DEPENDENCY}/BOOT-INF/lib /app/lib



COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF



COPY --from=builder ${DEPENDENCY}/BOOT-INF/classes /app



ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.MyApplication"]

发现在 Springboot2.2.9 ,是通过解压 jar 包,并 copy /BOOT-INF/classes/BOOT-INF/lib 以及 /META-INF 这三个文件夹来创建高效容器的 🐖 。

再次回忆下这几个文件夹 👇

img

img

img

当然,根据我们上文的结论,可以知道这里拷贝这个 META-INF 文件夹也没啥意义。毕竟最后已经指定 Main Class 去运行了。

这里我也去掉并做了个简单验证,依然部署成功,并且可以正常访问(当然,官方那样做可能也有其他我没考虑到的因素,就不多赘述啦🐖)

img

验证

接着,我们来看看 Springboot2.4.13 版本 的 👇

https://docs.spring.io/spring-boot/docs/2.4.13/reference/html/spring-boot-features.html#boot-features-container-images

FROM adoptopenjdk:11-jre-hotspot as builder



WORKDIR application



ARG JAR_FILE=target/*.jar



COPY ${JAR_FILE} application.jar



RUN java -Djarmode=layertools -jar application.jar extract



 



FROM adoptopenjdk:11-jre-hotspot



WORKDIR application



COPY --from=builder application/dependencies/ ./



COPY --from=builder application/spring-boot-loader/ ./



COPY --from=builder application/snapshot-dependencies/ ./



COPY --from=builder application/application/ ./



ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

这里就是我们上文中截取的代码了,当时也有强调说这个东西的作用 👇

img

所以再次回顾下这个官方的这段话,再次细品这段代码

COPY --from=builder application/dependencies/ ./



COPY --from=builder application/spring-boot-loader/ ./



COPY --from=builder application/snapshot-dependencies/ ./



COPY --from=builder application/application/ ./

可以发现,为了优化容器的创建,这里的 copy 顺序也是极为用心的。

先后顺序是

  1. 依赖包
  2. Springboot loader 源码
  3. 依赖包中的快照
  4. 应用代码,配置文件等

因为按照 docker 容器的创建原理,底层没改变的话,是可以直接使用缓存的。

这就意味着,我们创建容器时,很多都可以用到缓存,直到到达 应用代码和配置文件这一层 ,这就极大的提高了容器的创建速度。

细心的小伙伴可以从上面 “验证” 这张图中发现有 Using cache 的字眼😝

小结

那么,到了这里,你有没有感受到前面提到的改进原因呢?

  1. 在容器中,如果没有解压就直接运行一个 jar 包,它带来的开销是明显的
    感受:Springboot 2.2.9 和 Springboot 2.4.13 都提供 高效的 dockerfile 方式
  2. 将 应用代码和包依赖都混在同一层,也是可以被优化的地方。
    感受:Springboot 2.2.9 和 Springboot 2.4.13 都有改动,但是 2.4 中分的更细,而且基本上,2.4 的 dockerfile 在任何地方都可以直接用,不用做过多修改,很方便。

所以结论就是在 2.2.9 中就有了优化了,但是 2.3 之后又弄了个 layers.idx 来进一步优化,规范这个分层,提供了一个更简便的方式!

所以最后就变得更好使了😂

img


下面进入项目的搭建教学~

这个小项目主要是用来获取各种 验证码 的(中英文动态都有),是好久以前发现的,而且这个小 demo,还有隐藏的 API 等着小伙伴去发现。😄

感兴趣的小伙伴可以简单了解下这个 captcha 的生成,还是很有意思的😝

img

IDEA 部署 docker 容器

# 修改Docker服务文件,需要先切换到root用户 



vim /lib/systemd/system/docker.service



 



ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375



 



# 然后重启 docker

img

IDEA 中建一个 docker

img

创建 Dockerfile 容器。

img

最后运行即可~

可以在这里看到容器运行的 log。

img

项目地址

img

最后

本分就分享到这里了。

  1. 了解了 Springboot 在创建高效容器上的细节—— layers.idx。通过 jarmode 的 extract 参数去提取分好的层,提供高效的同时还方便开发人员去使用。
  2. 同时了解到 IDEA 怎么部署项目到远程容器。
  3. 又解决一个技术问题 嘻嘻嘻😝

img

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序源日志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值