Original Spring Boot 2.3 new features layered JAR

background

In our actual production containerization deployment process, we often encounter the situation that the Docker image is large and the deployment and release are slow

There are three main factors that affect the image size of docker:

    1. The size of the underlying mirror. Try to choose Apache as the basic image to reduce the built-in software of the operating system
    1. Number of layers of Dockerfile instruction. This requires us to optimize the Dockerfile to merge in one line as much as possible
    1. The size of the application jar. This is the key content to share today

helloworld image

Let's build the simplest web helloworld based on spring boot 2.3.0, and then build the image.

FROM adoptopenjdk:11-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
ENTRYPOINT ["java", "-jar application.jar"]
docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v1.0

View image hierarchy information

We use docker inspection demo:v1.0 Look at the hash value of each layer of this image

// demo:v1.0  Version image hierarchy information summary
"Layers": [
    "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
    "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
    "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
    "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
    "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
    "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
    "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
    "sha256:b87d2ff74819f83038ea2f89736a19cfcf99bfa080b8017d191c900a09a7524f"
]

helloworld upgrade rebuild

We make some changes to the helloworld program (simulating the development process), and then rebuild the image

docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v1.1

At this time, the image hierarchy information is as follows: docker inspect demo:v1.1

// demo:v1.1  Version image hierarchy information summary
"Layers": [
    "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
    "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
    "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
    "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
    "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
    "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
    "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
    "sha256:c1b6350d545fea605e0605c4bfd7f4529cfeee3f6759750d6a5ddeb9c882fc8f"
]

Compare v1.0 and v1.1 images

By comparing the image summary information of v1.0 and v1.1, we find that only the last layer has changed Dive is a Docker image analysis tool written in Go language To determine what was done at the last level

dive demo:v1.0 , you will see that the last jar is different, which causes the content of 16M to be rebuilt. When your business jar is large, this is the performance bottleneck

spring boot default package decryption

By default, you can see the following directory structure after extracting the jar built by spring boot. By default, it will be regarded as a whole, as a separate layer when building the image, without distinguishing between business classes and referenced third-party jars

META-INF/
  MANIFEST.MF
org/
  springframework/
    boot/
      loader/
BOOT-INF/
  classes/
  lib/

layer jar

As you can see from the above, the idea of layered jar is to subdivide the jar according to the rules. The business class and the three-party jar correspond to different layers of the image respectively. In this way, the business code can be changed with only a few changes to improve the construction speed.

Open layered packaging

  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
      <layers>
        <enabled>true</enabled>
      </layers>
    </configuration>
  </plugin>

Write support for layered Dockerfile

The core is to use the layertools tool provided by spring boot to split the jar s and load them separately through the COPY instruction

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

Build a new image and view hierarchical information

docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v2.0
"Layers": [
    "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
    "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
    "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
    "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
    "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
    "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
    "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
    "sha256:06fe18cf8ae7384f120f2c6a3a33b31999dd0460cf1edae45e8f13adeab35942",
    "sha256:16cf814564b8a667fcc9f07314b6084cbef8dc8c0a6565c7a2d91d74faf7e7de",
    "sha256:94be40f716016b68cdd6b99d2cb8154acf8475c3a170a898a22f95a8ef40ffd3",
    "sha256:427d87d6a5fe6da13cb4233939c3a1ff920bc6b4d2f14b5d78af7aef98fda7de"
]

Modify part of business code and rebuild

docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar  . -t demo:v2.1
"Layers": [
    "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e",
    "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6",
    "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794",
    "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233",
    "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab",
    "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d",
    "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535",
    "sha256:06fe18cf8ae7384f120f2c6a3a33b31999dd0460cf1edae45e8f13adeab35942",
    "sha256:16cf814564b8a667fcc9f07314b6084cbef8dc8c0a6565c7a2d91d74faf7e7de",
    "sha256:94be40f716016b68cdd6b99d2cb8154acf8475c3a170a898a22f95a8ef40ffd3",
    "sha256:8a20c60d361696a4e480fb6fbe1daf8b88bc54c579a98e209da1fb76e25de5aa"
]

View difference layer image

Change size of the last layer is 5KB

summary

Project recommendation: Welcome to RBAC permission management system of Spring Cloud and Spring Security OAuth2

Tags: Programming Spring Docker snapshot Java

Posted on Sun, 24 May 2020 19:09:01 -0700 by no3dfx