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

Practical record of solving MySQL deep paging problem

Table of contents Preface Why does limit deep pag...

In-depth analysis of MySQL deadlock issues

Preface If our business is at a very early stage ...

Text mode in IE! Introduction to the role of DOCTYPE

After solving the form auto-fill problem discussed...

Implementing simple tabs with js

Tab selection cards are used very frequently on r...

JavaScript Basics: Immediate Execution Function

Table of contents Immediately execute function fo...

How to install MySQL database on Debian 9 system

Preface Seeing the title, everyone should be thin...

Summary of Mysql-connector-java driver version issues

Mysql-connector-java driver version problem Since...

JavaScript function call classic example code

Table of contents JavaScript function call classi...

Vue implements small form validation function

This article example shares the specific code of ...

XHTML Getting Started Tutorial: Simple Web Page Creation

Create your first web page in one minute: Let'...

Detailed explanation of various join summaries of SQL

SQL Left Join, Right Join, Inner Join, and Natura...

Tutorial on installing MySQL 5.6 using RPM in CentOS

All previous projects were deployed in the Window...

How to implement remote automatic backup of MongoDB in Linux

Preface After reading the previous article about ...

WeChat applet wxs date and time processing implementation example

Table of contents 1. Timestamp to date 2. Convert...