Spring Boot layered packaging Docker image practice and analysis (recommended)

Spring Boot layered packaging Docker image practice and analysis (recommended)

1. Prepare the Spring Boot project

Simple, skip
Spring boot version > 2.3.x can simply write a hello world

2. Perform relevant configuration

Many blogs on the Internet emphasize that you need to manually configure the pom.xml to enable layered packaging:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <!--Enable tiered compilation support-->
                <layers>
                    <enabled>true</enabled>
                </layers>
            </configuration>
        </plugin>
    </plugins>
</build>

In version 2.3.x, it is a new feature and needs to be manually configured and enabled. However, the current Spring Boot version (using version 2.6.1) does not require manual configuration and supports this feature by default. (According to some blogs, it is enabled by default after version 2.4.x)

The current official documentation (version 2.6.0) also states that it is supported by default, but manual configuration is required only when this feature is not needed:

The repackaged archive includes the layers.idx file by default. To disable this feature, you can do so in the following manner:

<project>
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <configuration>
                   <layers>
                       <enabled>false</enabled>
                   </layers>
               </configuration>
           </plugin>
       </plugins>
   </build>
</project>

3. package

Execute mvn package to package and obtain the jar package file.

In fact, the essence is to use the repackage of the spring-boot-maven plug-in to get the complete jar package containing dependencies and the original jar package (the suffix .original is automatically added)
Open the jar package and you will find classpath.idx and layers.idx files in the BOOT-INF folder. Open them and take a look:

classpath.idx

- "BOOT-INF/lib/logback-classic-1.2.7.jar"

- "BOOT-INF/lib/logback-core-1.2.7.jar"

- "BOOT-INF/lib/log4j-to-slf4j-2.14.1.jar"

- "BOOT-INF/lib/log4j-api-2.14.1.jar"

- "BOOT-INF/lib/jul-to-slf4j-1.7.32.jar"

- "BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar"

- "BOOT-INF/lib/snakeyaml-1.29.jar"

- "BOOT-INF/lib/jackson-databind-2.13.0.jar"

- "BOOT-INF/lib/jackson-annotations-2.13.0.jar"

- "BOOT-INF/lib/jackson-core-2.13.0.jar"

- "BOOT-INF/lib/jackson-datatype-jdk8-2.13.0.jar"

- "BOOT-INF/lib/jackson-datatype-jsr310-2.13.0.jar"

- "BOOT-INF/lib/jackson-module-parameter-names-2.13.0.jar"

- "BOOT-INF/lib/tomcat-embed-core-9.0.55.jar"

- "BOOT-INF/lib/tomcat-embed-el-9.0.55.jar"

- "BOOT-INF/lib/tomcat-embed-websocket-9.0.55.jar"

- "BOOT-INF/lib/spring-web-5.3.13.jar"

- "BOOT-INF/lib/spring-beans-5.3.13.jar"

- "BOOT-INF/lib/spring-webmvc-5.3.13.jar"

- "BOOT-INF/lib/spring-aop-5.3.13.jar"

- "BOOT-INF/lib/spring-context-5.3.13.jar"

- "BOOT-INF/lib/spring-expression-5.3.13.jar"

- "BOOT-INF/lib/spring-boot-2.6.1.jar"

- "BOOT-INF/lib/spring-boot-autoconfigure-2.6.1.jar"

- "BOOT-INF/lib/slf4j-api-1.7.32.jar"

- "BOOT-INF/lib/spring-core-5.3.13.jar"

- "BOOT-INF/lib/spring-jcl-5.3.13.jar"

- "BOOT-INF/lib/spring-boot-jarmode-layertools-2.6.1.jar"

layers.idx

- "dependencies":

- "BOOT-INF/lib/"

- "spring-boot-loader":

- "org/"

- "snapshot-dependencies":

- "application":

- "BOOT-INF/classes/"

- "BOOT-INF/classpath.idx"

- "BOOT-INF/layers.idx"

- "META-INF/"

Verify again:

Layered information ok

4. Dockerfile

The Dockerfile file is also relatively conventional. It just uses the jarmode command to decompress the jar package before packaging the image. Then, during the packaging process, different layers are copied in sequence, and the application layer with the greatest possibility of change is placed at the end. In this way, the previous layers that have no changes can directly use Docker's cache to improve packaging efficiency.

FROM eclipse-temurin:8-jre-focal as builder

WORKDIR application

ARG JAR_FILE=target/*.jar

COPY ${JAR_FILE} application.jar

RUN java -Djarmode=layertools -jar application.jar extract

FROM eclipse-temurin:8-jre-focal

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/ ./

ENV TZ="Asia/Shanghai"

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

ENV JVM_OPTS=""

ENV JAVA_OPTS=""

ENTRYPOINT ["sh","-c","java $JVM_OPTS $JAVA_OPTS org.springframework.boot.loader.JarLauncher"]

5. Application modification & dive analysis

In fact, if you only package the image once, the advantages of layering will not be reflected, so you need to modify some content and then package it again (or multiple times, but the essence is the same, so only modify it once here)
Modify some application codes:

Re-pack the jar package and re-image, so that two images are obtained:

Use dive to analyze the two images:

It can be found that until the application layer (application/application/) is changed, the Id and Digest of the layers on both sides are exactly the same, so these layers can be reused, and the same layer will only be stored individually in the docker directory, which can greatly reduce the time for container compilation and push.
(The understanding of the specific layering of docker images is still limited, and I will learn more about it later)

This is the end of this article about the practice and analysis of Spring Boot layered packaging Docker image. For more relevant Spring Boot layered packaging Docker image content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Thoroughly understand the implementation of Docker image layering
  • Docker image layering and dockerfile writing skills
  • Detailed explanation of the principle of Docker image layering
  • A brief analysis of the considerations for Docker image layering
  • In-depth understanding of the layering of docker images (a must-read for beginners)

<<:  In-depth understanding of the seven communication methods of Vue components

>>:  Sample code for implementing dynamic glowing special effects animation of circles using pure CSS3

Recommend

Detailed explanation of Docker common commands Study03

Table of contents 1. Help Command 2. Mirror comma...

CSS code to distinguish ie8/ie9/ie10/ie11 chrome firefox

Website compatibility debugging is really annoyin...

Solution for using Baidu share on Https page

Since enabling https access for the entire site, ...

Detailed tutorial on installing Nginx 1.16.0 under Linux

Because I have been tinkering with Linux recently...

Understanding the MySQL query optimization process

Table of contents Parsers and preprocessors Query...

Detailed explanation of Javascript closures and applications

Table of contents Preface 1. What is a closure? 1...

Detailed process of drawing three-dimensional arrow lines using three.js

Demand: This demand is an urgent need! In a subwa...

Example operation MySQL short link

How to set up a MySQL short link 1. Check the mys...

Build Maven projects faster in Docker

Table of contents I. Overview 2. Conventional mul...

Vue simulates the shopping cart settlement function

This article example shares the specific code of ...

A record of a Linux server intrusion emergency response (summary)

Recently, we received a request for help from a c...

How to use Web front-end vector icons

Preface When writing front-end pages, we often us...

MySQL 1130 exception, unable to log in remotely solution

Table of contents question: 1. Enable remote logi...