应用准备容器化,因为几十个应用从测试到发布太麻烦了,而且还会因为环境的因素导致部署中出现各种问题。为了在开发、测试、生产都能保持一致的环境,就引进了容器技术,而目前常用的应用使用基于spring boot的。
在Spring Boot应用中,我们可以约定不同的标识来定义不同的环境。例如 dev 表示开发环境、test表示测试环境,对应的配置文件为apppcation-dev.yaml、apppcation-test.yaml。我们通过声明spring.profiles.active来激活对应的环境配置,例如激活dev环境时spring.profiles.active=dev。完整的启动命令为:
1
java -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=dev -jar spring-boot-app.jar
根据上面的命令编写一个能够适应多环境的Dockerfile:
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"
]
这样打包的Docker镜像就可以通过docker run添加额外的--env ACTIVE=test 来动态的改变环境。单纯的编写Dockerfile不方便我们DevOps。
docker 镜像生命周期
我们需要能够自动地构建、推送到仓库、拉取镜像、运行一系列流水线操作。好在市面上有很多工具来帮助我们实现这一过程。
spring-boot-maven-plugin
这个是Spring Boot官方的插件,在2.x的某个版本(2.3.x)提供了Docker镜像构建能力。
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>
配置好Docker私仓后就可以通过mvn clean spring-boot:build-image 进行构建镜像了。
这种方式好处就是无额外依赖,缺点就是需要从github下载构建元件,网络如果不好就容易失败。
Spotify Maven Plugin
Spotify Maven 插件是一个目前比较普遍的选择。它要求应用程序开发人员编写Dockerfile,并把Dockerfile放在项目src/main/docker目录下。然后你就可以通过引入:
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>repo.com/${project.artifactId}</repository>
</configuration>
</plugin>
这个插件提供了mvn dockerfile:build、mvn dockerfile:tag、mvn dockerfile:push三个命令分别用来构建、打标签、发布到远端私有仓库,非常简单。
这个是一个非常容易上手的插件,唯一的要求就是需要会编写Dockerfile,对定制化要求高的可以使用这个。
Jib Maven Plugin
它是谷歌开源的OCI镜像打包工具,可以用来打包Docker镜像,大部分情况下已经满足需要。但是如果你要定制化的话还是不容易的,需要阅读官方给的文档。最开始的Dockerfile如果使用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>
优点是不需要本地Docker环境,而且支持分层构建、镜像瘦身,上手容易;缺点是定制化比较困难。