Maven 插件之 docker-maven-plugin 的使用
docker-maven-plugin 介绍
在持续集成过程中,项目工程一般使用Maven编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便。docker-maven-plugin
插件就是为了帮助我们在Maven工程中,通过简单的配置,自动生成镜像并推送到仓库中。
docker-maven-plugin
:https://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
分为build
、tag
、push
,然后分别绑定 Maven 的package
、deploy
阶段,此时,我们只需要执行mvn deploy
就可以完成整个build
、tag
、push
操作,当我们执行mvn build
就只完成build
、tag
操作。除此此外,当我们想跳过某些步骤或者只执行某个步骤时,不需要修改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
时,执行build
、tag
操作,当执行mvn deploy
时,执行build
、tag
、push
操作。如果我们想跳过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=true 即build 完成后删除中间容器 |
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全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论