Maven 插件之 docker-maven-plugin 的使用

docker-maven-plugin 介绍

在持续集成过程中,项目工程一般使用Maven编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便。docker-maven-plugin插件就是为了帮助我们在Maven工程中,通过简单的配置,自动生成镜像并推送到仓库中。

docker-maven-pluginhttps://github.com/spotify/docker-maven-plugin

Demo 示例

这里我们测试 Java Maven 项目使用docker-maven插件打镜像,上传镜像等操作

配置 DOCKER_HOST

docker-maven-plugin插件默认连接本地Docker地址为:localhost:2375,所以需要先设置下环境变量。

DOCKER_HOST=tcp://<host>:2375

注意:如果没有设置DOCKER_HOST环境变量,可以命令行显示指定DOCKER_HOST来执行,如本机指定DOCKER_HOST

DOCKER_HOST=unix:///var/run/docker.sock mvn clean install docker:build

示例构建镜像

构建镜像可以使用以下两种方式,第一种是将构建信息指定到POM中,第二种是使用已存在的Dockerfile构建。
第一种方式,支持将FROM, ENTRYPOINT, CMD, MAINTAINER以及ADD信息配置在POM中,不需要使用Dockerfile配置。但是如果使用VOLUME或其他Dockerfile中的命令的时候,需要使用第二种方式,创建一个Dockerfile,并在POM中配置dockerDirectory来指定路径即可。

这里我们以一个 Java Maven 项目mavendemo作为示例演示一下。

指定构建信息到 POM 中构建

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            <configuration>
                <imageName>mavendemo</imageName>
                <baseImage>java</baseImage>
                <maintainer>docker_maven docker_maven@email.com</maintainer>
                <workdir>/ROOT</workdir>
                <cmd>["java", "-version"]</cmd>
                <entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
                <!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
                <resources>
                    <resource>
                        <targetPath>/ROOT</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${project.build.finalName}.jar</include>
                    </resource>
                </resources>
            </configuration>
        </plugin>
    </plugins>
</build>

使用 Dockerfile 构建

pom.xml配置

<build>
    <plugins>
         <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            <configuration>
                <imageName>mavendemo</imageName>
                <dockerDirectory>${basedir}/docker</dockerDirectory> <!-- 指定 Dockerfile 路径-->
                <!-- 这里是复制 jar 包到 docker 容器指定目录配置,也可以写到 Docokerfile 中 -->
                <resources>
                    <resource>
                        <targetPath>/ROOT</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${project.build.finalName}.jar</include>
                    </resource>
                </resources>
            </configuration>
        </plugin>   
    </plugins>
</build>

${basedir}/docker/Dockerfile配置

FROM java
MAINTAINER docker_maven docker_maven@email.com
WORKDIR /ROOT
CMD ["java", "-version"]
ENTRYPOINT ["java", "-jar", "${project.build.finalName}.jar"]

以上两种方式执行docker:build效果是一样的,执行输出过程大致如下:

[INFO] --- docker-maven-plugin:1.0.0:build (default-cli) @ mavenDemo ---
[INFO] Building image mavendemo
Step 1/5 : FROM java
 ---> d23bdf5b1b1b
Step 2/5 : MAINTAINER docker_maven docker_maven@email.com
 ---> Using cache
 ---> 2faf180d4a50
Step 3/5 : WORKDIR /ROOT
 ---> Using cache
 ---> 862210f7956a
Step 4/5 : ENTRYPOINT java -jar mavenDemo.jar
 ---> Running in 96bbe83de6ec
 ---> c29009c88993
Removing intermediate container 96bbe83de6ec
Step 5/5 : CMD java -version
 ---> Running in f69b8d2a75b1
 ---> bc8d54014325
Removing intermediate container f69b8d2a75b1
Successfully built bc8d54014325

执行完成后,使用docker images查看生成的镜像:

REPOSITORY       TAG           IMAGE ID            CREATED             SIZE
mavendemo        latest        333b429536b2        38 minutes ago      643 MB

执行命令

mvn clean package docker:build只执行 build 操作

mvn clean package docker:build -DpushImage执行 build 完成后 push 镜像

mvn clean package docker:build -DpushImageTag执行 build 并 push 指定 tag 的镜像

注意:这里必须指定至少一个imageTag,它可以配置到POM中,也可以在命令行指定。命令行指定如下:

mvn clean package docker:build -DpushImageTags -DdockerImageTags=imageTag_1 -DdockerImageTags=imageTag_2

POM 文件中指定配置如下:

<build>
  <plugins>
    ...
    <plugin>
      <configuration>
        ...
        <imageTags>
           <imageTag>imageTag_1</imageTag>
           <imageTag>imageTag_2</imageTag>
        </imageTags>
      </configuration>
    </plugin>
    ...
  </plugins>
</build>

绑定Docker 命令到 Maven 各个阶段

我们可以绑定Docker命令到 Maven 各个阶段,把Docker分为buildtagpush,然后分别绑定 Maven 的packagedeploy阶段,此时,我们只需要执行mvn deploy就可以完成整个buildtagpush操作,当我们执行mvn build就只完成buildtag操作。除此此外,当我们想跳过某些步骤或者只执行某个步骤时,不需要修改POM文件,只需要指定跳过Docker某个步骤即可。比如当我们工程已经配置好了自动化模板,但是这次我们只需要打镜像到本地自测,不想执行push阶段,那么此时执行要指定参数-DskipDockerPush就可跳过push操作。

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            <configuration>
                <imageName>mavendemo</imageName>
                <baseImage>java</baseImage>
                <maintainer>docker_maven docker_maven@email.com</maintainer>
                <workdir>/ROOT</workdir>
                <cmd>["java", "-version"]</cmd>
                <entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
                <resources>
                    <resource>
                        <targetPath>/ROOT</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>mavendemo:latest</image>
                        <newName>docker.io/yezhou/mavendemo:${project.version}</newName>
                    </configuration>
                </execution>
                <execution>
                    <id>push-image</id>
                    <phase>deploy</phase>
                    <goals>
                        <goal>push</goal>
                    </goals>
                    <configuration>
                        <imageName>docker.io/yezhou/mavendemo:${project.version}</imageName>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

以上示例,当我们执行mvn package时,执行buildtag操作,当执行mvn deploy时,执行buildtagpush操作。如果我们想跳过docker某个过程时,只需要:

  • -DskipDockerBuild 跳过 build 镜像
  • -DskipDockerTag 跳过 tag 镜像
  • -DskipDockerPush 跳过 push 镜像
  • -DskipDocker 跳过整个阶段

例如:我们想执行package时,跳过tag过程,那么就需要:mvn package -DskipDockerTag

使用私有 Docker 仓库地址

实际工作环境中,我们需要push镜像到我们私有Docker仓库中,使用docker-maven-plugin插件我们也是很容易实现,有几种方式实现:

(1)修改POM文件imageName操作

...
<configuration>
    <imageName>registry.example.com/yezhou/mavendemo:v1.0.0</imageName>
    ...
</configuration>
...

(2)修改POM文件中newName操作

...
<configuration>
    <imageName>mavendemo</imageName>
    ...
</configuration>
<execution>
    <id>tag-image</id>
    <phase>package</phase>
    <goals>
        <goal>tag</goal>
    </goals>
    <configuration>
        <image>mavendemo</image>
        <newName>registry.example.com/yezhou/mavendemo:v1.0.0</newName>
    </configuration>
</execution>
...

安全认证配置

当我们push镜像到Docker仓库中时,不管是共有还是私有,经常会需要安全认证,登录完成之后才可以进行操作。当然,我们可以通过命令行docker login -u user_name -p password docker_registry_host登录,但是对于自动化流程来说,就不是很方便了。使用docker-maven-plugin插件我们可以很容易实现安全认证。

首先在 Maven 的配置文件setting.xml中增加相关server配置,主要配置Docker registry用户认证信息。

<servers>
  <server>
    <id>my-docker-registry</id>
    <username>yezhou</username>
    <password>12345678</password>
    <configuration>
      <email>yezhou@mail.com</email>
    </configuration>
  </server>
</servers>

然后只需要在pom.xml中使用server id即可。

<plugin>
  <plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.0.0</version>
    <configuration>
      <imageName>registry.example.com/wanyang3/mavendemo:v1.0.0</imageName>
      ...
      <serverId>my-docker-registry</serverId>
    </configuration>
  </plugin>
</plugins>

其他参数

docker-maven-plugin插件还提供了很多很实用的配置,稍微列举几个参数:

参数 说明 默认值
<forceTags>true</forceTags> build时强制覆盖tag,配合imageTags使用 false
<noCache>true</noCache> build时,指定–no-cache不使用缓存 false
<pullOnBuild>true</pullOnBuild> build时,指定–pull=true每次都重新拉取基础镜像 false
<pushImage>true</pushImage> build完成后 push 镜像 false
<pushImageTag>true</pushImageTag> build完成后,push指定tag的镜像,配合imageTags使用 false
<retryPushCount>5</retryPushCount> push镜像失败,重试次数 5
<retryPushTimeout>10</retryPushTimeout> push镜像失败,重试时间 10s
<rm>true</rm> build时,指定–rm=truebuild完成后删除中间容器 false
<useGitCommitId>true</useGitCommitId> build时,使用最近的git commit id前7位作为tag
例如:image:b50b604,前提是不配置newName
false

配置案例

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <configuration>
                <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                <imageTags>
                    <imageTag>${project.version}</imageTag>
                    <imageTag>latest</imageTag>
                </imageTags>
                <forceTags>true</forceTags>
                <baseImage>${docker.baseImage}</baseImage>
                <volumes>${docker.volumes}</volumes>
                <env>
                    <JAVA_OPTS>${docker.java.opts}</JAVA_OPTS>
                </env>
                <entryPoint>["sh","-c","java $JAVA_OPTS ${docker.java.security.egd} -jar /${project.build.finalName}.jar"]</entryPoint>
                <resources>
                    <resource>
                        <targetPath>/</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${project.build.finalName}.jar</include>
                    </resource>
                </resources>
            </configuration>
        </plugin>
    </plugins>
    <finalName>${project.artifactId}</finalName>
</build>

FAQ

1、执行build images时,报错情况一:

[INFO] Building image mavendemo
org.apache.http.impl.execchain.RetryExec execute
I/O exception (java.io.IOException) caught when processing request to {}->unix://localhost:80: No such file or directory
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.0.0:build (default-cli) on project mavenDemo: Exception caught: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory -> [Help 1]

这个是因为Docker服务没有启动造成的,启动Docker即可

2、执行build images时,报错情况二:

ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.0.0:build (default-cli) on project mavenDemo: Exception caught: Request error: POST unix://localhost:80/build?t=mavenDemo: 500, body: {"message":"Error parsing reference: \"mavenDemo\" is not a valid repository/tag: repository name must be lowercase"}: HTTP 500 Internal Server Error -> [Help 1]

这个是因为镜像名字不正确,Docker镜像名称需匹配[a-z0-9-_.]

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/04/01/use-of-docker-aven-plugin-in-maven-plugin/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Maven 插件之 docker-maven-plugin 的使用
docker-maven-plugin 介绍 在持续集成过程中,项目工程一般使用Maven编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快……
<<上一篇
下一篇>>
文章目录
关闭
目 录