目录
- docker-maven-plugin 介绍
- 环境、软件准备
- Demo 示例
- 配置 DOCKER_HOST
- 示例构建镜像
- 指定构建信息到 POM 中构建
- 使用 Dockerfile 构建
- 使用命令
- 绑定 Docker 命令到 Maven各个阶段
- 使用私有Docker仓库地址
- 安全认证配置
- FAQ
1、docker-maven-plugin 介绍
在我们持续集成过程中,项目工程一般使用 Maven 编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便。docker-maven-plugin 插件就是为了帮助我们在Maven工程中,通过简单的配置,自动生成镜像并推送到仓库中。
2、环境、软件准备
本次演示环境,我是在本机 Mac OX 上操作,以下是安装的软件及版本:
- Docker:version 17.03.1-ce
- Maven:version 3.3.9
- Java: version 1.8.0_91
- docker-maven-plugin:1.0.0
注意:这里我们要测试 Java Maven 项目用 docker-maven 插件打镜像,上传镜像等操作,所以需要先安装一下 Docker、Maven、Java,这里忽略安装过程。
3、Demo 示例
3.1 配置 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。
3.2 示例构建镜像
构建镜像可以使用一下两种方式,第一种是将构建信息指定到 POM 中,第二种是使用已存在的 Dockerfile 构建。
第一种方式,支持将FROM,ENTRYPOINT,CMD,MAINTAINER 以及ADD 信息配置在 POM 中,不需要使用 Dockerfile 配置。但是如果使用VOLUME 或其他 Dockerfile 中的命令的时候,需要使用第二种方式,创建一个 Dockerfile,并在 POM 中配置dockerDirectory 来指定路径即可。
这里我们以一个 Java Maven 项目 mavendemo 作为示例演示一下。
3.2.1 指定构建信息到 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>3.2.2 使用 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
---> d23bdf5b1b1bStep 2/5 : MAINTAINER docker_maven docker_maven@email.com
--->Using cache --->2faf180d4a50Step 3/5 : WORKDIR /ROOT
--->Using cache --->862210f7956aStep 4/5 : ENTRYPOINT java -jar mavenDemo.jar
--->Runningin96bbe83de6ec ---> c29009c88993Removing intermediate container 96bbe83de6ec
Step 5/5 : CMD java -version
--->Runningin f69b8d2a75b1 ---> bc8d54014325Removing intermediate container f69b8d2a75b1
Successfully built bc8d54014325执行完成后,使用docker images查看生成的镜像:
REPOSITORYTAG IMAGE ID CREATED SIZE
mavendemo latest333b429536b238 minutes ago643 MB3.3 执行命令
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>3.4 绑定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/wanyang3/mavendemo:${project.version}</newName></configuration></execution><execution><id>push-image</id><phase>deploy</phase><goals><goal>push</goal></goals><configuration><imageName>docker.io/wanyang3/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。
3.5 使用私有 Docker 仓库地址
实际工作环境中,我们需要 push 镜像到我们私有 Docker 仓库中,使用d ocker-maven-plugin 插件我们也是很容易实现,有几种方式实现:
一、修改 POM 文件 imageName 操作
...
<configuration>
<imageName>registry.example.com/wanyang3/mavendemo:v1.0.0</imageName>...
</configuration>...二、修改 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/wanyang3/mavendemo:v1.0.0</newName>
</configuration>
</execution>...3.6 安全认证配置
当我们 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>wanyang3</username><password>12345678</password><configuration><email>wanyang3@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>3.7 其他参数
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 |
4、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 fileor directory
[ERROR] Failed to execute goalcom.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 fileor directory -> [Help1]这个是因为 Docker 服务没有启动造成的,启动 Docker 即可。
2、执行 build images 时,报错情况二:
ERROR] Failedto execute goal com.spotify:docker-maven-plugin:1.0.0:build (default-cli)onprojectmavenDemo:Exceptioncaught:Requesterror:POSTunix://localhost:80/build?t=mavenDemo:500,body: {"message":"Error parsing reference: \"mavenDemo\" is not a valid repository/tag: repository name must be lowercase"}:HTTP500InternalServerError -> [Help1]这个是因为镜像名字不正确,Docker 镜像名称需匹配[a-z0-9-_.]。
参考资料