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-_.]。

參考資料

原文地址:https://blog.csdn.net/aixiaoyang168/article/details/77453974