[Daily Short] 26 - Spring Boot 2.3 Added Layered Jar Package Feature for Docker Image

background

Spring Boot 2.3 (M2 as of now) provides a new feature, Layered Jar, for containerized deployment.Generally speaking, Spring Boot programs are built in the way of fat jar. File sizes vary from 50M to 100M, which is actually not friendly to docker image.The Docker image itself is a hierarchical structure, so if there is no change in a layer, you do not have to upload it when pull ing, and if there is a change, you upload the entire layer.In a program, the change frequency of code and resources of the program itself is much greater than that of dependent libraries. Most of the time, it is a waste to upload the entire jar file due to several lines of code change, whether in storage or time efficiency. The latter is especially distracting under domestic network speed.

Layered Jar

The new feature layered jar provides a supporting tool for content separation with different change frequencies, and it is easy to build a docker image on top of it.Essentially, this feature is a new layout provided by org.springframework.boot:spring-boot-maven-plugin. When packaging with a new layout, a spring-boot-layertools jar is packaged into a fat jar, and the new feature is provided by this jar.Rather than delving into the implementation details, focus on how you can use this feature modally to reap benefits.

There is very little to do to use this new feature, starting with adding a layout configuration to the pom, and I guess this option will become the default in the future without any explicit configuration.

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <configuration>
        <layout>LAYERED_JAR</layout>
      </configuration>
    </plugin>
    ...
  </plugins>
  ...
</build>

The new addition is these three lines

<configuration>
  <layout>LAYERED_JAR</layout>
</configuration>

After adding the configuration, the package is packaged and the following commands can be executed to verify that the configuration is correct or not

java -Djarmode=layertools -jar <target.jar>

An example output:

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

This is all that needs to be done on maven, and gradle refers to maven similarly.Then you need to do a little more work in Dockerfile, which uses the docker's multi-stage build functionality (17.05 added functionality, almost three years ago, hopefully nobody said this version was too new ~).An example 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

Explain the above Dockerfile line by line:

  1. The #01, #07 2 FROM s can be maintained as the basic mirror used at runtime.
  2. The source of COPY at #04 varies depending on the docker plug-in used. The plug-in used in this article is io.fabric8:docker-maven-plugin:0.33.0.The destination file should remain application.jar, which should match the jar file name of #05;;
  3. #If errors need to be checked for missing parameters, such as #20 requiring--enable-preview, then #05needs to be added--enable-preview;
  4. #09, #11, #18 have nothing to do with this article, but they are good practices for containerization of Spring Boot. You can copy them and have the opportunity to talk about them in the future.
  5. #10 is also a good practice - run by non-root users and delete this line if you encounter problems;
  6. One ENTRYPOINT copy of #13, #14, #15, #16, #204 COPYs is the key to this new feature.

The mirrored content built with this Dockerfile is then broken down into multiple layers, affecting more layers in turn when changing source code, resources, snapshot dependencies, and official dependencies, minimizing storage and transfer time each time an upload warehouse is built.

summary

layered jar is worth using in terms of ease of use and effectiveness achieved.To use this feature, you only need to open a configuration item in the pom and use a Dockerfile template that hardly needs any modifications, with almost no burden and considerable benefits.

Two other posts related to the content covered in this article are available for reference
[Daily Short] 23 - Dynamically specify Java startup parameters for containers
[Daily Short] 0 - Timzone settings for Linux

Finally, repeat the Dockerfile without a line number for easy copying

FROM azul/zulu-openjdk:13 as builder

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

Tags: Programming Maven Java Spring Docker

Posted on Tue, 03 Mar 2020 12:01:07 -0800 by onewaylife