目錄
- 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
---> 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
3.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 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-_.]。
參考資料