1. 程式人生 > >Maven 外掛之 docker-maven-plugin 的使用

Maven 外掛之 docker-maven-plugin 的使用

目錄

  • docker-maven-plugin 介紹
  • 環境、軟體準備
  • Demo 示例
    • 配置 DOCKER_HOST
    • 示例構建映象
      • 指定構建資訊到 POM 中構建
      • 使用 Dockerfile 構建
    • 使用命令
    • 繫結 Docker 命令到 Maven各個階段
    • 使用私有Docker倉庫地址
    • 安全認證配置
  • FAQ

1、docker-maven-plugin 介紹

在我們持續整合過程中,專案工程一般使用 Maven 編譯打包,然後生成映象,通過映象上線,能夠大大提供上線效率,同時能夠快速動態擴容,快速回滾,著實很方便。docker-maven-plugin 外掛就是為了幫助我們在Maven工程中,通過簡單的配置,自動生成映象並推送到倉庫中。

2、環境、軟體準備

本次演示環境,我是在本機 Mac OX 上操作,以下是安裝的軟體及版本:

  1. Docker:version 17.03.1-ce
  2. Maven:version 3.3.9
  3. Java: version 1.8.0_91
  4. 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 [email protected]</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 [email protected]
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 [email protected]
 ---> 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 [email protected]</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>[email protected]</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-_.]。

參考資料