dockerfile-maven 使用 实践

摘要:将基于 MavenJava 项目容器化,spotifydockerfile-maven 是一个不错的选择,使用简单,基本涵盖了所需功能,下面我们给出一种最佳实践的使用方法。

需要解决的问题

对于将项目容器,最需要解决什么呢?我们首先罗列一下

  1. Dockerfile 的编写
  2. 依赖文件的寻址
  3. image 的不同 tag 指定
  4. CI/CD 的自动 Docker 镜像构建和推送

第一个问题不在插件的解决范围内,但是第二个问题该插件就可以提供很好的支持,当然也就间接的为 Dockerfile 的编写提供的便利。

下面我们根据 Jhipster 默认的 Docker 配置文件介绍如何为项目加入 Dockfile 通过 Maven 构建的是方法。

文件组织

src/main/ 目录下加入 docker 文件夹,用于维护所有的 docker 相关的文件

enter description here

pom 配置

这里有三个相关的插件:

  1. maven-resources-plugin
  2. git-commit-id-plugin
  3. dockerfile-maven-plugin

maven-resources-plugin

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
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
<executions>
<execution>
<id>docker-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target/</outputDirectory>
<resources>
<resource>
<directory>src/main/docker/</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*.yml</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

我们前面知道,docker 相关的文件都放置在了 src/main/docker/ 所以这个插件配置就是为了将 docker 相关文件作为 resource 放置到 target 目录下,当然这里所有 yml 文件被排除了,因为这些文件使用来运行 docker-compose 的,镜像的构建不需要这些文件。

那么为什么要放到 target 的目录呢? 因为我们最终项目的 war 包是被构建到 target 目录下,而下面我们知道, dockerfile-maven 插件可以指定构建的目录,这样只需要将项目的 target 目录设置为 contextDirectory 这时候我们 dockerfile 构建的当前目录就包含了所有必须的内容。这一点我们可以让 dockerfile 的编写更加方便,无需解决各种路径的依赖问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM openjdk:8-jre-alpine

ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
JHIPSTER_SLEEP=0 \
JAVA_OPTS=""

# Add a jhipster user to run our application so that it doesn't need to run as root
RUN adduser -D -s /bin/sh jhipster
WORKDIR /home/jhipster

ADD entrypoint.sh entrypoint.sh
RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh
USER jhipster

ADD *.war app.war

ENTRYPOINT ["./entrypoint.sh"]

EXPOSE 8080

我们可以看到在执行 ADD 命令的时候,没有任何路径,这是因为当前的路径下,已经包含了 wardockerfile 本身。

git-commit-id-plugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>${git-commit-id-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<includeOnlyProperties>
<includeOnlyProperty>^git.commit.id.abbrev$</includeOnlyProperty>
<includeOnlyProperty>^git.commit.id.describe$</includeOnlyProperty>
<includeOnlyProperty>^git.branch$</includeOnlyProperty>
</includeOnlyProperties>
</configuration>
</plugin>

该插件是为了给 pom.xml 提供一些和 git 相关的参数,比如当前的 commitid${git.commit.id.describe}

dockerfile-maven-plugin

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
44
45
46
47
48
49
50
51
52
53
54
 <plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-plugin.version}</version>
<executions>
<!--
Uncomment the section below to build the docker image with mvn package and and push it with mvn deploy
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
-->
<execution>
<id>tag-latest</id>
<phase>none</phase>
<goals>
<goal>build</goal>
<goal>tag</goal>
<goal>push</goal>
</goals>
</execution>
<execution>
<id>version</id>
<phase>none</phase>
<goals>
<goal>build</goal>
<goal>tag</goal>
<goal>push</goal>
</goals>
<configuration>
<tag>${project.version}</tag>
</configuration>
</execution>
<execution>
<id>commit</id>
<phase>none</phase>
<goals>
<goal>build</goal>
<goal>tag</goal>
<goal>push</goal>
</goals>
<configuration>
<tag>${git.commit.id.describe}</tag>
</configuration>
</execution>
</executions>
<configuration>
<repository>devtools</repository>
<contextDirectory>${project.build.directory}</contextDirectory>
</configuration>
</plugin>

首先 configuration 中配置 repository 的名字以及 contextDirectory,这里注意 repository 最终会成为生成的 image 的名字,如果你的 DockerHub 上有前缀,那么这里也应该有,比如 xxx/yyy,如果是私有的 docker registery, 也可以将域名也加入其中。

这里有两种方式进行构建:

  1. 一种是通过执行 maven 的某些生命周期,从而自动完成构建。
  2. 手工执行 plugingoal 以及附加 id 构建

第一种,需要将如下代码 uncomment

1
2
3
4
5
6
7
8
9
10
<!--
Uncomment the section below to build the docker image with mvn package and and push it with mvn deploy
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
-->

第二种:

1
2
mvn dockerfile:build@version -Dsso.version=6.0.12.65
docker push docker.dualshield-cloud.com/dualshield-sso:6.0.65

对于 execution 中的 configuration 的参数,我们可以自行指定,这样在 CI/CD 的过程可以动态的指定 tag