本文主要介绍如何通过 docker-maven-plugin 插件把 Java 服务构建成 docker 镜像;文中所使用到的软件版本:Docker 20.10.17、Java 1.8.0_341、SpringBoot 2.7.12、Maven 3.8.4、docker-maven-plugin 1.2.2。

1、docker-maven-plugin 插件信息

使用如下命令查看插件详细信息:

mvn help:describe -DartifactId=docker-maven-plugin -DgroupId=com.spotify -Dversion=1.2.2 -Ddetail

1.1、插件目标

该插件包含 5 个目标:

目标

说明

docker:build

构建镜像

docker:help

显示帮助信息

docker:push

上传镜像

docker:removeImage

删除镜像

docker:tag

给镜像打标签

1.2、常用配置参数

1.2.1、docker:build 参数

参数

说明

baseImage

基础镜像,如果设置了 dockerDirectory,忽略该参数 

buildArgs

定义 docker build 时的参数,可以在 Dockerfile 文件中使用这些参数

cmd

定义容器默认的运行程序,如果设置了 dockerDirectory,忽略该参数 

dockerDirectory

Dockerfie 文件所在目录(相对 pom.xml 的相对目录),如果没有配置该参数,将会根据 baseImage、entryPoint、cmd、maintainer 参数自动生成 Dockerfie

dockerHost

docker 地址

entryPoint

定义容器默认的运行程序,如果设置了 dockerDirectory,忽略该参数 

imageName

镜像名称

maintainer

镜像维护者,如果设置了 dockerDirectory,忽略该参数

resources

定义构建镜像所需的资源,这些资源会先 copy 到 Dockerfile 所在目录下

resources/resource

一个资源配置

resources/resource/targetPath

定义资源 copy 到的目标目录,该配置会在 Dockerfile 所在目录中创建对应参数值的目录

resources/resource/directory

资源所在目录

resources/resource/include

资源包含的文件

1.2.2、docker:removeImage 参数

参数

说明

dockerHost

docker 地址

imageName

删除的镜像名称,包括 REPOSITORY 和 TAG

imageTags

与 imageName 中 REPOSITORY 一致, 其他需删除的 TAG

1.2.3、docker:tag 参数

参数

说明

dockerHost

docker 地址

image

镜像名称或镜像 id

newName

新的标签名称

1.2.4、docker:push 参数

参数

说明

serverId

服务 id,对应 Maven settings.xml 中 servers/server 节点配置信息

registryUrl

被推送的镜像仓库

imageName

推送的镜像名称

2、docker-maven-plugin 插件使用

2.1、新建 SpringBoot 工程

<groupId>com.abc</groupId>
<artifactId>demo-general</artifactId>
<version>1.0.0</version>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.12</version>
    <relativePath />
</parent>

2.2、在 POM 中设置 build 信息

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.2.2</version>
    <configuration>
        <dockerHost>http://10.49.196.33:2375</dockerHost>
        <baseImage>adoptopenjdk/openjdk8:latest</baseImage>
        <imageName>${project.artifactId}:${project.version}</imageName>
        <cmd>["java", "-jar", "/root/${project.build.finalName}.jar"]</cmd>
        <resources>
            <resource>
                <targetPath>/root</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

 执行如下命令生成镜像:

mvn package docker:build

先打包,然后生成镜像;镜像可在 docker 中查看:

Maven 入门实战(3)--docker-maven-plugin 插件使用_docker

2.3、使用 Dockerfile

2.3.1、新建 Dockerfile 文件

在项目下新建 docker 目录,并在该目录下新建 Dockerfile 文件:

Maven 入门实战(3)--docker-maven-plugin 插件使用_docker_02

Dockerfile 文件文件内容为:

From adoptopenjdk/openjdk8
ARG jarFile
COPY ${jarFile} /root/demo-general-1.0.0.jar
EXPOSE 9090

CMD ["java", "-jar", "/root/demo-general-1.0.0.jar"]

adoptopenjdk/openjdk8 为直接 pull 到本地的官方 jdk 镜像。

2.3.2、docker-maven-plugin 插件配置

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.2.2</version>
    <configuration>
        <dockerHost>http://10.49.196.33:2375</dockerHost>
        <imageName>${project.artifactId}:${project.version}</imageName>
        <dockerDirectory>docker</dockerDirectory>
        <buildArgs>
            <jarFile>${project.build.finalName}.jar</jarFile>
        </buildArgs>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>

执行如下命令生成镜像:

mvn package docker:build

2.4、绑定 Docker 命令到 Maven 生命周期阶段

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.2.2</version>
    <configuration>
        <dockerHost>http://10.49.196.33:2375</dockerHost>
        <imageName>${project.artifactId}:${project.version}</imageName>
        <dockerDirectory>docker</dockerDirectory>
        <buildArgs>
            <jarFile>${project.build.finalName}.jar</jarFile>
        </buildArgs>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
    <executions>
        <execution>
            <id>build-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
        <execution>
            <id>tag-image</id>
            <phase>package</phase>
            <goals>
                <goal>tag</goal>
            </goals>
            <configuration>
                <image>${project.artifactId}:${project.version}</image>
                <newName>10.49.196.34:18080/test/${project.artifactId}:${project.version}</newName>
            </configuration>
        </execution>
        <execution>
            <id>push-image</id>
            <phase>verify</phase>
            <goals>
                <goal>push</goal>
            </goals>
            <configuration>
                <serverId>my-harbor</serverId>
                <registryUrl>http://10.49.196.34:18080</registryUrl>
                <imageName>10.49.196.34:18080/test/${project.artifactId}:${project.version}</imageName>
            </configuration>
        </execution>
    </executions>
</plugin>

上面的配置在打包阶段绑定了生成镜像及给镜像打标签的目标,执行 mvn package 命令后,到 docker 中查看镜像信息:

Maven 入门实战(3)--docker-maven-plugin 插件使用_docker_03

在 verify 阶段绑定了 push 镜像的目标,在 Maven settings.xml 中配置远程仓库 Harbor 的用户名密码:

<servers>
  <server>
    <id>my-harbor</id>
    <username>admin</username>
    <password>Harbor12345</password>
  </server>
</servers>

执行 mvn verify 命令后,到 Harbor 中查看镜像信息:

Maven 入门实战(3)--docker-maven-plugin 插件使用_docker_04

3、替换插件

该插件在 Docker 的基础上引入了额外的抽象和配置,容易给用户带来困扰;官网建议使用 dockerfile-maven-plugin 来替换该插件。

Maven 入门实战(3)--docker-maven-plugin 插件使用_maven_05