Spring Boot 2.3.0.M1刚刚发布,它带来了一些有趣的新功能,可以帮助您将Spring Boot应用程序打包到Docker镜像中。在此博客文章中,我们将介绍开发人员创建Docker镜像的典型方式,并展示如何使用这些新功能进行改进。
普通Docker技术:
创建一个类似以下内容的dockerfile:
FROM openjdk:8-jdk-alpine EXPOSE 8080 ARG JAR_FILE=target/my-application.jar ADD ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"] |
尽管这种方法很好用,简洁明了,但是有些事情不是最理想的。
Spring Boot 2.3.0.M1中引入了两个新功能,以帮助改进这些现有技术:buildpack支持和分层jar。
buildpack
Spring Boot 2.3.0.M1直接支持Maven和Gradle的buildpack。这意味着您只需键入一个命令,即可将明智的映像快速获取到本地运行的Docker守护程序中。对于Maven,您可以mvn spring-boot:build-image使用Gradle 键入gradle bootBuildImage。发布镜像的名称将是您的应用程序名称,标签将是版本。
让我们看一下使用Maven的示例:
首先使用start.spring.io创建一个新的Spring Boot项目:
$ curl https://start.spring.io/starter.zip -d bootVersion=2.3.0.M1 -d dependencies=web -o demo.zip $ unzip demo.zip |
下一步在本地机器上安装Docker并运行,然后:
$ ./mvnw spring-boot:build-image
第一次运行将花费一些时间,但后续调用会更快。
您的应用程序已编译,打包并转换为Docker映像。您可以使用以下方法进行测试:
$ docker run -it -p8080:8080 demo:0.0.1-SNAPSHOT
Spring Boot提供的内置支持提供了一种开始使用buildpack的好方法。由于它是buildpack平台规范的实现,因此也很容易迁移到功能更强大的buildpack工具,例如pack或kpack确信会生成相同的映像。
分层jar
Spring Boot始终支持其自己的“胖jar”格式,该格式允许您创建可以使用java -jar运行。如果您曾经研究过该jar的内容,则会看到一个类似以下的结构:
META-INF / MANIFEST.MF org / springframework / boot / loader / ... BOOT-INF / classes / ... lib / ... |
分为三个主要部分:
- classes是用于引导jar加载的类
- Spring Boot应用程序类是在 BOOT-INF/classes
- 依赖是在 BOOT-INF/lib
由于这种格式是Spring Boot特有的,因此我们有可能以有趣的方式进行发展。借助Spring Boot,2.3.0.M1我们提供了layout一种称为的新类型LAYERED_JAR。
如果您选择采用分层格式并查看jar结构,则会看到以下内容:
META-INF/ MANIFEST.MF org/ springframework/ boot/ loader/ ... BOOT-INF/ layers/ <name>/ classes/ ... lib/ ... <name>/ classes/ ... lib/ ... layers.idx |
现在lib和classes文件夹已拆分并分类为图层。还有一个新layers.idx文件,提供了添加图层的顺序。
最初,我们提供了以下现成的图层:
- dependencies (对于常规发布的依赖项)
- snapshot-dependencies (对于快照依赖性)
- resources (用于静态资源)
- application (用于应用程序类和资源)
此分层旨在根据应用程序构建之间更改的可能性来分离代码。库代码不太可能在内部版本之间进行更改,因此将其放置在自己的层中,以允许工具重新使用缓存中的层。应用程序代码更可能在内部版本之间进行更改,因此将其隔离在单独的层中。
提取图层
jarmode是启动jar时可以设置的特殊系统属性。它允许引导代码运行与您的应用程序完全不同的内容。例如,提取图层。
编写dockerfile
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layout>LAYERED_JAR</layout> </configuration> </plugin> </plugins> </build> |
然后重新构建Jar:
mvn clean package
现在应该有一个带有jarmode支持的分层jar 。使用以下命令进行测试:
$ java -Djarmode=layertools -jar target/demo-0.0.1-SNAPSHOT.jar list |
应该看到以下输出,该输出告诉我们应添加的图层及其顺序:
dependencies snapshot-dependencies resources application |
可以制作一个dockerfile用于提取并复制每个图层的文件。这是一个例子:
ROM 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/snapshot-dependencies/ ./ COPY --from=builder application/resources/ ./ COPY --from=builder application/application/ ./ ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] |
这是一个多阶段的dockerfile。该builder阶段提取以后需要的文件夹。每个COPY命令都与我们前面列出的层有关。
要构建镜像,我们可以运行:
$ docker build . --tag demo
测试:
$ docker run -it -p8080:8080 demo:latest
总结
使用buildpacks,dockerfiles和现有插件(例如jib),这些都是创建Docker镜像的方法。每种方法都有其优点和缺点,但是希望无论您选择哪种方法,我们在Spring Boot 2.3中提供的新功能都将有所帮助。
猜你喜欢