[每日短篇]26SpringBoot2.3为DockerImage增加的分层Jar包特性
Layered Jar
新特性 layered jar 为不同变更频率内容分离提供了支持工具,在此基础上分层构建 docker image 就变得很容易了。本质上这个特性是 org.springframework.boot:spring-boot-maven-plugin
提供的一种新的 layout
,当使用新 layout
打包时,一个 spring-boot-layertools
jar 会打包到 fat jar 中,新特性是由这个 jar 提供的。这里不深入解析实现细节,而是重点关注如何模式化使用这个特性获得收益。
要使用这个新特性需要做的事情非常少,首先是在 pom 中增加 layout
配置,我猜未来这个选项会成为默认值,从而不需任何显式配置。
<build> <plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>LAYERED_JAR</layout>
</configuration>
</plugin>
...
</plugins>
...
</build>
新增的部分就是这 3 行
<configuration> <layout>LAYERED_JAR</layout>
</configuration>
增加配置之后 package
打包,然后可以执行以下命令验证配置正确与否
java -Djarmode=layertools -jar <target.jar>
一个示例输出:
Usage: java -Djarmode=layertools -jar metis-server-0.1.0-SNAPSHOT.jar
Available commands:
list List layers from the jar that can be extracted
extract Extracts layers from the jar for image creation
help Help about any command
这是 maven 上所有需要做的事情,gradle 参照 maven 也可以类似处理。然后需要在 Dockerfile 中再做一点处理,这用到了 docker 的多阶段构建功能(17.05 增加的功能,几乎 3 年前,希望没人说这版本太新~)。一个示例 Dockerfile
FROM azul/zulu-openjdk:13 as builder #01 #02
WORKDIR application #03
COPY /maven/${project.build.finalName}.jar application.jar #04
RUN java -Djarmode=layertools -jar application.jar extract #05
#06
FROM azul/zulu-openjdk:13 #07
#08
WORKDIR /opt/bin/ #09
USER 1000:1000 #10
EXPOSE 8080 #11
#12
COPY --from=builder application/dependencies/ ./ #13
COPY --from=builder application/snapshot-dependencies/ ./ #14
COPY --from=builder application/resources/ ./ #15
COPY --from=builder application/application/ ./ #16
#17
ENV TZ=Asia/Shanghai #18
#19
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] #20
对上面的 Dockerfile
逐行解释一下:
#01
、#07
2 个FROM
保持统一为运行时使用的基础镜像即可;#04
处COPY
的源根据使用的 docker 插件不同会有所变化,本文使用的插件为io.fabric8:docker-maven-plugin:0.33.0
。目的文件保持application.jar
即可,它要跟#05
的 jar 文件名一致;#05
如果报错需要检查是否遗漏了参数,比如#20
需要--enable-preview
的话#05
也需要加--enable-preview
;#09
、#11
、#18
跟本文无关,但是算是 Spring Boot 容器化的良好实践,可以照抄,日后有机会专文再讲;#10
也是良好实践——非 root 用户运行,如果遇到相关问题可以删除此行;#13
、#14
、#15
、#16
、#20
4 个COPY
1 个ENTRYPOINT
照抄即可,这是本文新特性的关键。
然后,用这个 Dockerfile
构建出来的镜像内容已经是拆解分成多层的镜像了,当变更源码、资源、快照版依赖、正式版依赖时会依次影响更多层镜像,从而实现每次构建上传仓库时存储和传输耗时最小化。
总结
无论从易用程度还是达到的效果上讲,layered jar 都非常值得使用。要使用该特性只需要开启 pom 中一个配置项并使用一个几乎不需要任何修改的 Dockerfile
模板,几乎零负担获得可观的收益。
与本文所涉及内容有所关联的另外 2 篇帖子可供参考
[每日短篇] 23 - 动态给容器指定 Java 启动参数
[每日短篇] 0 - Linux 的 timezone 设置
最后把不带行号的 Dockerfile
再重复一次以方便复制
FROM azul/zulu-openjdk:13 as builderWORKDIR application
COPY /maven/${project.build.finalName}.jar application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM azul/zulu-openjdk:13
WORKDIR /opt/bin/
USER 1000:1000
EXPOSE 8080
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/resources/ ./
COPY --from=builder application/application/ ./
ENV TZ=Asia/Shanghai
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
以上是 [每日短篇]26SpringBoot2.3为DockerImage增加的分层Jar包特性 的全部内容, 来源链接: utcz.com/z/514077.html