Recently the company’s application ready to containerize, because dozens of applications from testing to release is too much trouble, and also because of environmental factors lead to a variety of problems in the deployment. In order to maintain a consistent environment in development, testing, production, the introduction of container technology, first take the edge of the project to try, to gain experience. Today a brief summary of several common Docker packaging tools.

Spring Boot Docker

In a Spring Boot application, we can agree on different identifiers to define different environments. For example, dev means development environment, test means test environment, and the corresponding configuration files are application-dev.yaml and application-test.yaml. We activate the corresponding environment configuration by declaring spring.profiles.active, e.g. spring.profiles.active=dev when activating the dev environment. The complete startup command is as follows.

1
java -Djava.security.egd=file:/dev/./urandom  -Dspring.profiles.active=dev -jar spring-boot-app.jar 

Write a Dockerfile that can adapt to multiple environments based on the above command.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 引入 openjdk 镜像
FROM adoptopenjdk/openjdk8
# 声明作者
LABEL AUTHOR=felord OG=felord.cn
# 挂载几个有用的文件夹 比如日志
VOLUME ["/tmp","/logs"]
# 声明一个环境参数用来动态启用配置文件 默认dev
ENV ACTIVE=dev
# 暴露端口
EXPOSE 8080
# 复制并修改应用打包后的jar文件名称
ADD /target/flyway-spring-boot-1.0.0.jar app.jar
# 容器启动时第一个运行的命令 用来启动应用
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=${ACTIVE}","-jar","app.jar"]

This way the packaged Docker image can be dynamically changed by adding an additional -env ACTIVE=test to docker run to change the environment. Writing Dockerfile alone is not convenient for our DevOps.

We need to be able to automate the process of building, pushing to repositories, pulling images, and running a series of pipeline operations. The good thing is that there are many tools on the market to help us with this process.

spring-boot-maven-plugin

This is an official Spring Boot plugin that provides Docker image building capabilities in some version of 2.x.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<project>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                    <name>docker.repo.com/library/${project.artifactId}:${project.version}</name>
                        <publish>true</publish>
                    </image>
                    <docker>
                        <publishRegistry>
                            <username>user</username>
                            <password>secret</password>
                            <url>https://docker.repo.com/v1/</url>
                            <email>user@example.com</email>
                        </publishRegistry>
                    </docker>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Once you have configured your Docker private storage, you can build the image via mvn clean spring-boot:build-image.

The advantage of this approach is that there are no additional dependencies, but the disadvantage is that you need to download the build components from github, which can easily fail if you have a bad network.

Spotify Maven Plugin

The Spotify Maven plugin is a more common choice today. It requires application developers to write a Dockerfile and place the Dockerfile in the project src/main/docker directory. Import the following components.

1
2
3
4
5
6
7
8
<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.4.8</version>
    <configuration>
        <repository>myorg/${project.artifactId}</repository>
    </configuration>
</plugin>

This plugin provides mvn dockerfile:build, mvn dockerfile:tag and mvn dockerfile:push commands to build, tag and publish to a remote private repository respectively, very simple.

This is a very easy plugin to get started with. The only requirement is that you need to be able to write a Dockerfile, so you can use this if you have high customization requirements.

Jib Maven Plugin

This once I have been introduced in an earlier article, you can learn more about it. It is Google’s open source OCI image packaging tool, which can be used to package Docker images, and in most cases already meet the needs. But if you want to customize it is still not easy, you need to read the official documentation given. The very first Dockerfile needs to be configured this way if you use JIb.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <from>
            <image>adoptopenjdk/openjdk8</image>
        </from>
        <to>
            <image>docker.repo.com/library/${project.artifactId}</image>
            <auth>
                <username>felord</username>
                <password>xxxxxx</password>
            </auth>
            <tags>
                <tag>${project.version}</tag>
            </tags>
        </to>
        <extraDirectories>
            <paths>
                <path>
                    <from>target/${project.artifactId}-${project.version}.jar</from>
                    <includes>*.jar</includes>
                    <into>/app.jar</into>
                </path>
            </paths>
        </extraDirectories>
        <containerizingMode>packaged</containerizingMode>
        <container>
            <volumes>/tmp,/logs</volumes>
            <ports>
                <port>8080</port>
            </ports>
            <environment>
                <active>dev</active>
            </environment>
            <entrypoint>
                java,-Djava.security.egd=file:/dev/./urandom,-Dspring.profiles.active=${active},-jar,/app.jar
            </entrypoint>
            <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
        </container>
    </configuration>
</plugin>

The advantage is that it does not require a local Docker environment and supports layered builds, image thinning, and easy to get started; the disadvantage is that customization is more difficult.

Reference https://felord.cn/spring-docker-ex.html