Java SpringBoot project construction Docker image tuning practice

        I saw this document online and thought it was very good. I reprint it here to mainly learn the ideas of using hierarchical caching and processing image size in this article.

Reprinted from: Java SpringBoot project construction Docker image tuning practice | Xiaodudin Technology Stack

PS: It has been verified in production practice to solve the problem that in the production environment, the network speed and bandwidth are small, and each push and pull of the image affects the online service. The image is built according to the method in this article. In addition to the slow pull, push and build of the image for the first time, the second The second, third... times were all hundreds of K in size. The speed was very fast, and the construction, packaging, and push were completed within a few seconds.

Foreword:

        In the previous era of Spring Cloud microservices, "Jar packages" were the basis of services. Each service was packaged into a Jar for interrelationships and calls between services. Now, with the popularity of Kubernetes, it has changed to one image and one service, and Kubernetes relies on the unified orchestration of images to uniformly manage services. In the process of practicing Kubernetes microservices, the most exposed one is definitely the Docker image. Since the programming language I use is Java, I have a lot of exposure to the Java SpringBoot project, so I am more concerned about how to better compile Docker images through Dockerfile.

        Simply put, Kubernetes microservices are the arrangement, combination and mutual adjustment of a group of images. Therefore, how to compile the images will make the service performance better, make the image construction, push and pull faster, and make it occupy less network resources. Here Optimizing and making it easier to use has become a top priority, and it is also an issue worth considering. Here I will briefly describe how to write a Dockerfile to package the Docker image of the SpringBoot project.

System environment:


1. Explore how regular Springboot compiles Docker images

        Here we will use regular SpringBoot to compile the Dockerfile of the Docker image, and feel how the image compiled in this way works.

1. Prepare the SpringBoot project to compile the image

        Here we prepare an ordinary springboot project compiled by Maven to build the Docker image. The project content is as shown in the figure below. You can see that what is used is the Jar file of the application inside, which is stored in the image to complete the image construction. Task.

  • jar file size: 70.86mb

2. Prepare the Dockerfile

        Building a Docker image requires preparing a Dockerfile file in advance. The contents of this Dockerfile file are the instructions to be executed to build the Docker image. The following is a commonly used Dockerfile for building Docker images with SpringBoot. Put it into the Java source directory (the upper-level directory of the target) and ensure that the path set in the Dockerfile script set below corresponds to the target path.

FROM openjdk:8u212-b04-jre-slim
VOLUME /tmp
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
ENV APP_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]

3. Build Docker image

        Build the Docker image through the Docker build command and observe the compilation time.

Since the image needs to be pushed to the Aliyun Docker warehouse later, the image prefix is ​​Aliyun.

  • time: This parameter will display the elapsed time of the execution process
$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1 .

Build process

Sending build context to Docker daemon  148.7MB
Step 1/7 : FROM openjdk:8u212-b04-jre-slim
8u212-b04-jre-slim: Pulling from library/openjdk
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
Digest: sha256:a5bcd678408a5fe94d13e486d500983ee6fa594940cbbe137670fbb90030456c
Status: Downloaded newer image for openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/7 : VOLUME /tmp
 ---> Running in 13a67ab65d2b
Removing intermediate container 13a67ab65d2b
 ---> 52011f49ddef
Step 3/7 : ADD target/*.jar app.jar
 ---> 26aa41a404fd
Step 4/7 : RUN sh -c 'touch /app.jar'
 ---> Running in 722e7e44e04d
Removing intermediate container 722e7e44e04d
 ---> 7baedb10ec62
Step 5/7 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in 2681d0c5edac
Removing intermediate container 2681d0c5edac
 ---> 5ef4a794b992
Step 6/7 : ENV APP_OPTS=""
 ---> Running in 5c8924a2a49d
Removing intermediate container 5c8924a2a49d
 ---> fba87c19053a
Step 7/7 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in c4cf97009b3c
Removing intermediate container c4cf97009b3c
 ---> d5f30cdfeb81
Successfully built d5f30cdfeb81
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m13.778s
user	0m0.078s
sys	0m0.153s

I saw that this compilation was completed within 14 seconds .

4. Push the image to the image warehouse

Push the image to the Aliyun warehouse, then check and record the push time

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

Implementation process

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
cc1a2376d7c0: Pushed 
2b940d07e9e7: Pushed 
9544e87fb8dc: Pushed 
feb5d0e1e192: Pushed 
8fd22162ddab: Pushed 
6270adb5794c: Pushed 
0.0.1: digest: sha256:dc60d304383b1441941ca4e9abc08db775d7be57ccb7c534c929b34ff064a62f size: 1583

real	0m24.335s
user	0m0.052s
sys	0m0.059s

Saw it completed within 25s this time .

5. Pull the image

Here, switch to another server to perform the image pull operation and observe the image pull time.

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

Pull process

0.0.1: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
4847672cbfa5: Pull complete 
b60476972fc4: Pull complete 
Digest: sha256:dc60d304383b1441941ca4e9abc08db775d7be57ccb7c534c929b34ff064a62f
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m27.528s
user	0m0.033s
sys	0m0.192s

It can be seen that this pull took a total of 28 seconds to complete.

6. Modify the Java source code and repackage the Jar and try again

        Here, the content of the JAVA file of the source code is modified, and then the Jar package is repackaged, so that the compilation, push, and pull processes are tried again. Since Docker uses hierarchical caching when executing the build, this is a faster process.

(1), compile

$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2 .

Sending build context to Docker daemon  148.7MB
Step 1/7 : FROM openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/7 : VOLUME /tmp
 ---> Using cache
 ---> 52011f49ddef
Step 3/7 : ADD target/*.jar app.jar
 ---> c67160dd2a23
Step 4/7 : RUN sh -c 'touch /app.jar'
 ---> Running in 474900d843a2
Removing intermediate container 474900d843a2
 ---> 3ce9a8bb2600
Step 5/7 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in f48620b1ad36
Removing intermediate container f48620b1ad36
 ---> 0478f8f14e5b
Step 6/7 : ENV APP_OPTS=""
 ---> Running in 98485fb15fc8
Removing intermediate container 98485fb15fc8
 ---> 0b567c848027
Step 7/7 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in e32242fc6efe
Removing intermediate container e32242fc6efe
 ---> 7b223b23ebfd
Successfully built 7b223b23ebfd
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m3.190s
user	0m0.039s
sys	0m0.403s

        You can see that in the process of compiling the image, the first 1 and 2 layers are cached, so the speed is very fast. The total compilation process takes less than 4 seconds to complete.

(2), push

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
d66a2fec30b5: Pushed 
f4da2c7581aa: Pushed 
9544e87fb8dc: Layer already exists 
feb5d0e1e192: Layer already exists 
8fd22162ddab: Layer already exists 
6270adb5794c: Layer already exists 

real	0m20.816s
user	0m0.024s
sys	0m0.081s

        You can see that only the first two layers are pushed, and the other four layers are not pushed because the remote warehouse has not changed. The entire push process takes 21 seconds to complete.

(3), pull

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

0.0.2: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Already exists 
04305660f45e: Already exists 
bbe7020b5561: Already exists 
d7e364f0d94a: Pull complete 
8d688ada35b1: Pull complete 
Digest: sha256:7c13c40fa92ec2fdc3a8dfdd3232be1be9c1a1a99bf123743ff2a43907ee03dc
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m23.214s
user	0m0.053s
sys	0m0.097s

        The first four layers are cached locally and only the last two layers with changes are pulled. This process takes 24 seconds to complete.

7. Feelings during the use of mirroring

        By building a Docker image for the SpringBoot project in this way, my feeling is that as long as there is a slight change in the source code, the SpringBoot project needs to compile the project through Maven and then build the Docker image, each time a 70M+ When the application Jar file is stored in Docker, sometimes even if one letter is changed, the entire program Jar may have to be saved into the Docker image again. Then during the push and pull process, a large image or image must be pushed each time. Pulling a large image for transfer feels very inconvenient.

2. Understand Docker layering and caching mechanism

1. Introduction to Docker hierarchical caching

        In order to save storage space, Docker adopts the concept of layered storage. Different images can share access to the basic image. For information about image layering, you can visit the image layering in Docker’s official documentation. There is a detailed introduction to the relevant documents. The address is as follows:

        Docker image cache official documentation: https://docs.docker.com/storage/storagedriver/

        During the process of building the image, Docker will gradually execute the instructions in the Dockerfile in the order specified in the Dockerfile. As each instruction is checked, Docker will look in its cache for an existing image that can be reused, rather than creating a new (duplicate) image.

        Each line of command in the Dockerfile creates a new layer, including the changes to the file system before and after the execution of this line of command.

        In order to optimize this process, Docker uses a caching mechanism: as long as this line of command remains unchanged, the result will be the same as the last time, and the last result can be used directly.

        In order to take full advantage of hierarchical caching, we must understand how the command line in the Dockerfile works, especially the RUN, ADD and COPY commands.

2. Layering of SpringBoot Docker image

        After SpringBoot is compiled into an image, the bottom layer will be a system, such as Ubantu. The upper layer is the dependent JDK layer, and then the SpringBoot layer. The bottom two layers are dependent on the basic image, and there is not much room for optimization. Therefore, when optimizing the image, we consider more about how to optimize the SpringBoot layer and ponder this layer.

3. What causes Jar to become bloated?

        From the above experiment, we learned that the reason why each compilation, push, and pull process is relatively slow is the huge image file. After understanding the concept of Docker caching, I came up with the idea that if files that do not change frequently are cached, files that are frequently changed will not be cached. Since SpringBoot projects change frequently, how should we use the caching mechanism to implement it? If the cache is forcibly used, wouldn't the image taken every time be the old program content in the cache?

        So consider what files are included in the application Jar package, which Java files are frequently changed, and which are not frequently changed. In this regard, the following will analyze the application Jar package created by SpringBoot.

1. Unzip the Jar package and view the contents

Display the decompressed list and view the size of each folder

$ tree -L 3 --si --du

.
├── [ 74M]  BOOT-INF 
│   ├── [2.1k]  classes
│   └── [ 74M]  lib
├── [ 649]  META-INF
│   ├── [ 552]  MANIFEST.MF
│   └── [  59]  maven
└── [  67]  org
    └── [  38]  springframework

        You can see that the largest file is the lib folder. When you open this folder, there are a bunch of related dependency Jars. One of the Jars is not big, but a bunch of Jars combined will be very big. Generally, SpringBoot projects depend on the Jar size. Maintain at 40MB ~ 160MB.

        Looking at the org folder, the total code inside is only a few hundred KB. Therefore, the SpringBoot program Jar package is composed of these Classes files and dependent Jars. These dependent Jars total 74 MB, accounting for almost the entire size of the application Jar package.

2. New ideas to solve bloat

        If a Jar package only contains class files, the size of the Jar package may be several hundred KB. Now we want to explore, if we separate the Jar and class that the lib depends on, set the Jar package of the application to only contain class files, and put the Jar files in the lib folder outside the SpringBoot Jar.

        When we write a program, the Jar that it often relies on does not change frequently. What changes most is the source code program. The Jar package that it relies on is very large and the source code is very small. Think about it carefully, if you set up a separate layer of cache for the Jar package that the application depends on when packaging it into a Docker image, and the application Jar package only contains Class files, then during the compilation, push, and pull processes of Docker, except for the first time In addition to executing everything, in the subsequent compilation, push, and pull processes, only the changed Jar file containing only Class will be operated, which is only a few hundred KB. It can be said that this process can be completed instantly. So think about how to separate the dependent Jar package and the application Jar package in the lib folder.

3. How to solve the separation of lib and class files

        After searching a lot of relevant information, I found that SpringBoot's Maven plug-in does a lot of things when executing Maven to compile and build Jar packages. If you change the packaging logic of some plug-ins, you can add the application dependencies to the lib folder when building the application Jar package . All Jars are copied outside the application Jar, leaving only the compiled bytecode class files .

        After many searches on the Internet, I found an implementation method, as follows, introduce these Maven tools into the project pom.xml

<build>
    <plugins>
        <!--设置应用 Main 参数启动依赖查找的地址指向外部 lib 文件夹-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <!--设置 SpringBoot 打包插件不包含任何 Jar 依赖包-->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                 <includes>
                     <include>
                         <groupId>nothing</groupId>
                         <artifactId>nothing</artifactId>
                     </include>
                 </includes>
            </configuration>
        </plugin>
        <!--设置将 lib 拷贝到应用 Jar 外面-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Execute Maven command to package Jar

$ mvn clean install

After the Maven command is executed, view the target directory as shown below:

        You can see that the application jar has become very small, and the lib folder has been placed outside the jar. The jar package is no longer integrated. Instead, the lib address is specified when the application jar is running so that it can be loaded.

        No matter what, we need to test whether this Jar file can run normally. Only normal execution can prove that this solution is feasible.

Execute the following command to test whether the jar can start normally:

$ java -jar springboot-helloworld-0.0.1.jar

        I can see the running log during the running process, and it shows that the operation is successful, which means that this solution is feasible. However, our transformation work is not over yet, and we will continue the Dockerfile transformation work.

4. Let’s talk about how to transform Springboot and compile Docker images

Project Github address: https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-dockerfile

1. Modify the Dockerfile file

        To modify the Dockerfile above, you need to add the following instruction:

COPY target/lib/ ./lib/

        This command is used to copy the dependent Jar in the lib directory to the image. The rest remains consistent with the Dockerfile above .

FROM openjdk:8u212-b04-jre-slim
VOLUME /tmp
COPY target/lib/ ./lib/
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
ENV APP_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]

A new layer of instructions is added here, which is used to copy the lib folder to the image. Due to the Docker caching mechanism, this layer must be before copying the application Jar. In this way, after the transformation, every time the dependent Jar in the lib folder is not If the layer is changed, a new layer will not be created, but the cache will be reused.

2. First compilation, push, and pull after transforming the Docker image

        Here we start to actually try to perform compilation, push, and pull to test its speed. Before execution, we first clear all resources related to the last image of the server to reduce the impact on the test environment.

(1) Compilation speed test and record

$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1 .

Sending build context to Docker daemon  223.2MB
Step 1/8 : FROM openjdk:8u212-b04-jre-slim
8u212-b04-jre-slim: Pulling from library/openjdk
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
Digest: sha256:a5bcd678408a5fe94d13e486d500983ee6fa594940cbbe137670fbb90030456c
Status: Downloaded newer image for openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/8 : VOLUME /tmp
 ---> Running in 529369acab24
Removing intermediate container 529369acab24
 ---> ad689d937118
Step 3/8 : COPY target/lib/ ./lib/
 ---> 029a64c15853
Step 4/8 : ADD target/*.jar app.jar
 ---> 6265a83a1b90
Step 5/8 : RUN sh -c 'touch /app.jar'
 ---> Running in 839032a58e6b
Removing intermediate container 839032a58e6b
 ---> 5d877dc35b2b
Step 6/8 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in 4043994c5fed
Removing intermediate container 4043994c5fed
 ---> 7cf32beb571f
Step 7/8 : ENV APP_OPTS=""
 ---> Running in b7dcfa10458a
Removing intermediate container b7dcfa10458a
 ---> b6b332bcf0e6
Step 8/8 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in 539093461b59
Removing intermediate container 539093461b59
 ---> d4c095c4ffec
Successfully built d4c095c4ffec
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m22.983s
user	0m0.051s
sys	0m0.540s

(2) Push speed test and record

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
c16749205e05: Pushed 
7fef1a146748: Pushed 
a3bae74bbdf2: Pushed 
9544e87fb8dc: Pushed
feb5d0e1e192: Pushed
8fd22162ddab: Pushed
6270adb5794c: Pushed 
0.0.1: digest: sha256:e2f4db740880dbe5338b823112ba9467fedf8b27cd75572611d0d3837c80f157 size: 1789

real	0m30.335s
user	0m0.052s
sys	0m0.059s

(3) Pull speed test and record

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

0.0.1: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
de6c4f15d75b: Pull complete 
7066947b7d89: Pull complete 
e0742de67c75: Pull complete 
Digest: sha256:e2f4db740880dbe5338b823112ba9467fedf8b27cd75572611d0d3837c80f157
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m36.585s
user	0m0.024s
sys	0m0.092s

3. Compile, push, and pull again

        We execute the image build again to test Step 3/8 : COPY target/lib/ ./lib/whether the image in the cache is reused when the build is completed.

(1) Compilation speed test and record

$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2 .

Sending build context to Docker daemon  223.2MB
Step 1/8 : FROM openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/8 : VOLUME /tmp
 ---> Using cache
 ---> ad689d937118
Step 3/8 : COPY target/lib/ ./lib/
 ---> Using cache
 ---> 029a64c15853
Step 4/8 : ADD target/*.jar app.jar
 ---> 563773953844
Step 5/8 : RUN sh -c 'touch /app.jar'
 ---> Running in 3b9df57802bd
Removing intermediate container 3b9df57802bd
 ---> 706a0d47317f
Step 6/8 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in defda61452bf
Removing intermediate container defda61452bf
 ---> 742c7c926374
Step 7/8 : ENV APP_OPTS=""
 ---> Running in f09b81d054dd
Removing intermediate container f09b81d054dd
 ---> 929ed5f8b12a
Step 8/8 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in 5dc66a8fc1e6
Removing intermediate container 5dc66a8fc1e6
 ---> c4942b10992c
Successfully built c4942b10992c
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m2.524s
user	0m0.051s
sys	0m0.493s

As you can see, the entire compilation process only took 2.5 seconds for the cache used directly in layer 3 this time.

(2) Push speed test and record

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
d719b9540809: Pushed 
d45bf4c5fb92: Pushed 
a3bae74bbdf2: Layer already exists 
9544e87fb8dc: Layer already exists 
feb5d0e1e192: Layer already exists 
8fd22162ddab: Layer already exists 
6270adb5794c: Layer already exists 
0.0.2: digest: sha256:b46d81b153ec64321caaae7ab28da0e362ed7d720a7f0775ea8d1f7bef310d00 size: 1789

real	0m0.168s
user	0m0.016s
sys	0m0.032s

You can see that the image push was completed within 0.2s .

(3) Pull speed test and record

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

0.0.2: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Already exists 
04305660f45e: Already exists 
bbe7020b5561: Already exists 
de6c4f15d75b: Already exists 
1c77cc70cc41: Pull complete 
aa5b8cbca568: Pull complete 
Digest: sha256:b46d81b153ec64321caaae7ab28da0e362ed7d720a7f0775ea8d1f7bef310d00
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m1.947s
user	0m0.017s
sys	0m0.042s

You can see that the image pull was completed within 2 seconds .

5. Final summary

        Due to network fluctuations and system changes, the time can only be used as a reference, but the compilation, push, and pull processes are indeed much faster. Most of the files are cached, and the traffic interaction of only a few hundred KB is naturally faster than dozens of MB or even hundreds of MB are much faster.

        Finally, let me explain that this approach only provides a reference. Since the Docker mirroring of the current microservice service, the entire image is maintained instead of a service program, so the concern is whether the Docker image can run normally and how to build the image. It will make the built image more usable.

        In the production environment, because the version changes slowly and will not be updated at every turn, it is best to stick to the original SpringBoot image compilation method in the production environment to ensure installation (unless the construction method has been verified by a large number of examples).

Guess you like

Origin blog.csdn.net/yangyangye/article/details/132623528