More and more projects are containerized and Docker has become an important tool in software development. We can usually package the fat jar of a Spring Boot application as a docker image with the following Dockerfile
.
It looks good, but you will find that if we change the business code, the image will be rebuilt, even if you just change a string. If you use CI/CD to build and deploy Docker images, you will find that sometimes the build time in the CI pipeline can be very long, or even stuck, especially when there are more images. So we project to optimize this place.
Docker’s layering mechanism
To optimize it, we need to understand the build hierarchy of Docker images. Because Docker image consists of many layers, each layer represents a command in the Dockerfile. Each layer is an increment of the changes on the base layer, and incremental builds are done from the bottom up.
This mechanism is actually where Docker gets its name from, like dock workers yarding cargo.
Also when we build a Docker image, it is extracted in layers and cached in the host, and these layers can be reused, which gives us the opportunity to optimize.
Like the container above, if we put the container that is prone to change on the bottom layer, every time we change it we need to remove the top of it; if we put it on the bottom layer we can reduce the workload. The same is true for the build of Docker images.
Optimization of Spring Boot images
Spring Boot’s fat jar can be significantly more efficient if it can be split into layers to build one layer and reuse the duplicate layers from the host cache. So Spring Boot applications can be divided into layers according to the frequency of changes as follows.
dependencies
(dependencies generally don’t change much)spring-boot-loader
(the spring boot loader doesn’t change much either)snapshot-dependencies
(snapshot dependencies, for snapshot versions of dependencies, the update iterations will be faster)application
(business layer, which is what we change most often)
Since Spring Boot 3.x, Spring Boot provides the spring-boot-jarmode-layertools
jar package, which will be added to the application jar as a dependency. To start the jar via the layertools
jar mode.
|
|
The index file layers.idx
will be generated for the above four levels.
Above is the information about the Spring Boot application jar built in this schema, we can see these two things.
This feature relies on the
spring-boot-maven-plugin
plugin.
We just need to change the Dockerfile
to the following.
|
|
You can then reuse the Docker caching layer in the host to speed up the build efficiency. The build command is.
|
|
It will then output.
|
|
java -Djarmode=layertools -jar
is not recommended for use in startup scripts, only recommended for use in builds .
Additions
Regarding the plugin there are currently version differences, in Spring Boot 2.3 you need to add the following configuration.
By default in springboot 2.4.x and above.
By enabling the layered build Spring Boot application image, you can obviously feel the speed of pushing the image a lot faster (of course, this is the case of the dependency has not changed); in addition, when pulling the image from the remote only need to pull the change layer, the speed is also significantly faster; on the build is actually built twice, although with the cache, the efficiency actually does not change much. That is to say, in the mirror of the network transmission on the layered build has obvious advantages, worth a try.
Reference
https://felord.cn/docker-layer-spring-boot.html