Springboot 是这样提高创建 docker 容器的效率的

前言

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

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

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

这里应该改为

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

改进原因

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 的,也还是这几句话:pig:)

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 ,感觉说的很有道理 哈哈哈

默默三连认同

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

求证

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

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

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

这里我将 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 这三个文件夹来创建高效容器的 :pig2: 。

再次回忆下这几个文件夹 :point_down:

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

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

验证

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

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"]

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

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

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 的字眼:stuck_out_tongue_closed_eyes:

小结

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

  1. 在容器中,如果没有解压就直接运行一个 jar 包,它带来的开销是明显的

  2. 将 应用代码和包依赖都混在同一层,也是可以被优化的地方。

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

所以最后就变得更好使了:joy:

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

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

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

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

IDEA 中建一个 docker

创建 Dockerfile 容器。

最后运行即可~

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

项目地址 

https://github.com/Java4ye/springboot-demo-4ye

最后

本分就分享到这里了。

  1. 了解了 Springboot 在创建高效容器上的细节—— layers.idx 。通过 jarmode 的 extract 参数去提取分好的层,提供高效的同时还方便开发人员去使用。

  2. 同时了解到 IDEA 怎么部署项目到远程容器。

  3. 又解决一个技术问题 嘻嘻嘻:stuck_out_tongue_closed_eyes:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值