使用Spring Boot編寫了一個(gè)微服務(wù)后,如何將構(gòu)建應(yīng)用并打包成docker鏡像,推送到docker倉庫,以供測試環(huán)境測試。
docker-maven-plugin插件可以完成這項(xiàng)任務(wù)。
最近使用了docker-maven-plugin插件,想寫一篇關(guān)于使用總結(jié)的文章,但發(fā)現(xiàn)它在github上的README.md寫的很好了,決定對它翻譯一下。
docker-maven-plugin的Github地址:https://github.com/spotify/docker-maven-plugin
該插件是基于maven插件,用來構(gòu)建docker鏡像,當(dāng)然也可以通過在系統(tǒng)中配置Dockerfile的方式構(gòu)建鏡像。
目的
你可以使用該插件在你的maven項(xiàng)目中創(chuàng)建一個(gè)Docker鏡像,比方說,build 過程可以為java服務(wù)輸出一個(gè)可以運(yùn)行該服務(wù)的Docker鏡像。
步驟
dockerfile提供了兩種配置方式,一種是通過Dockerfile文件,一種是直接在pom.xml配置。
你可以直接在pom.xml文件中指定base image,entry point, cmd, maintainer 和files,而不用通過Dockerfile的方式。
當(dāng)然通過pom.xml文件的方式支持一些簡單的命令,如果你需要VOLUMN命令(或者其他pom.xml不支持使用的命令),還是需要通過將命令寫入Dockerfile,并通過在pom中配置dockerDirectory來引入該Dockerfile
默認(rèn)情況下,該插件通過訪問localhost:2375來連接本地docker,可以通過設(shè)置DOCKER_HOST 環(huán)境變量來連接docker.
DOCKER_HOST=tcp://<host>:2375
在POM中聲明構(gòu)建信息
下面的代碼示例是創(chuàng)建了名為example的新鏡像,將項(xiàng)目編譯的jar包拷貝到鏡像中,并設(shè)置了一個(gè)entrypoint去運(yùn)行這個(gè)jar,在下面的代碼中可以改變VERSION GOES HERE改變插件的版本,目前最新的版本是1.0.0
<build>
<plugins>
...
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>VERSION GOES HERE</version>
<configuration>
<imageName>example</imageName>
<baseImage>java</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<!-- copy the service's jar file from target into the root directory of the image -->
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
...
</plugins>
</build>
參數(shù)解釋:
- imageName:鏡像的名稱,可以通過${project.groupId}/${project.artifactId}:${project.version} 動態(tài)制定鏡像名稱
當(dāng)然也可以在前面加上鏡像地址,比如127.0.0.1:5000,以聲明將構(gòu)建好的鏡像存儲在本地 - baseImage: 基礎(chǔ)鏡像,這里是相當(dāng)于Dockerfile的FROM java
- resources 下的配置:構(gòu)建時(shí)會生成docker文件夾,這里指生成文件夾的內(nèi)容來源,包含了mvn clean package 之后的target的文件和生成的jar包。
使用Dockerfile
為了使用Dockerfile,必須在pom的文件中通過dockerDirectory來指明Dockerfile文件的所在目錄。如果配置了dockerDirectory,baseImage,maintainer,cmd和entryPoint配置將忽略。下面的配置會將dockerDirectory的內(nèi)容拷貝值${project.build.directory}/docker,使用resouces元素可以拷貝其他的文件,比如生成jar包文件。
<build>
<plugins>
...
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>VERSION GOES HERE</version>
<configuration>
<imageName>example</imageName>
<dockerDirectory>docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
...
</plugins>
</build>
使用
按照上面的配置之后,可以使用如下命令生成一個(gè)鏡像
mvn clean package docker:build
將生成的鏡像推送到鏡像注冊中心,通過pushImage標(biāo)簽
mvn clean package docker:build -DpushImage
如果推送制定tags 的鏡像,可使用pushImageTag標(biāo)簽
mvn clean package docker:build -DpushImageTag
為了是的上述的命令執(zhí)行成功,需要在pom中配置imageTag,可以配置多個(gè)imageTag
<build>
<plugins>
...
<plugin>
<configuration>
...
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
</configuration>
</plugin>
...
</plugins>
</build>
如果你想強(qiáng)制docker在每次新的構(gòu)建上覆蓋鏡像tags,可配置foreceTags
<build>
<plugins>
...
<plugin>
<configuration>
...
<!-- optionally overwrite tags every time image is built with docker:build -->
<forceTags>true</forceTags>
<imageTags>
...
</imageTags>
</configuration>
</plugin>
...
</plugins>
</build>
也可以在構(gòu)建的命令行上添加上鏡像tags:
mvn ... docker:build -DpushImageTags -DdockerImageTags=latest -DdockerImageTags=another-tag
綁定docker命令到maven phases
你可以將bind,tag&push 目標(biāo)綁定到maven phases,這樣僅僅通過運(yùn)行mvn deploy命令就能完成項(xiàng)目built,tagged,pushed。如果你有一個(gè)多模塊項(xiàng)目,當(dāng)通過綁定,在父項(xiàng)目運(yùn)行maven命令的同時(shí),子模塊項(xiàng)目可以自動構(gòu)建。鏡像
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>VERSION GOES HERE</version>
<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>my-image:${project.version}</image>
<newName>registry.example.com/my-image:${project.version}</newName>
</configuration>
</execution>
<execution>
<id>push-image</id>
<phase>deploy</phase>
<goals>
<goal>push</goal>
</goals>
<configuration>
<imageName>registry.example.com/my-image:${project.version}</imageName>
</configuration>
</execution>
</executions>
</plugin>
可以通過一下命令跳過docker構(gòu)建的階段
- DskipDockerBuild 跳過鏡像構(gòu)建
- DskipDockerTag 跳過鏡像tag設(shè)置
- DskipDockerPush 跳過鏡像推送
- DskipDocker 跳過所有的鏡像構(gòu)建目標(biāo)
刪除一個(gè)名稱為foobar的鏡像,可以運(yùn)行如下命令
mvn docker:removeImage -DimageName=foobar
獲取完成的配置選項(xiàng)列表,可運(yùn)行如下命令:
mvn com.spotify:docker-maven-plugin:<version>:help -Ddetail=true
使用私有鏡像中心
為了將鏡像推送到私有的鏡像注冊中心,docker需要在鏡像tag之前用注冊中心的地址作為前綴。比如需要推送my-image到registry.example.com,那么這個(gè)鏡像需要命名為registry.example.com/my-image
最簡單的方法就是在<imageName>中配置:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>registry.example.com/my-image</imageName>
...
這樣,當(dāng)你通過命令docker:build -DpushImage或者docker:push推送鏡像時(shí),docker引擎會將鏡像推送到registry.example.com.
當(dāng)然你可以在docker:build命令中通過 docker:tag -DpushImage對創(chuàng)建的鏡像加上私有鏡像注冊中心的地址,如不配置,則會推送到默認(rèn)的鏡像中心,即Docker hub;你也可如下這樣配置:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>my-image</imageName>
...
</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>my-image</image>
<newName>registry.example.com/my-image</newName>
</configuration>
</execution>
</executions>
</plugin>
認(rèn)證
支持三種認(rèn)證方式:
讀取本地配置文件,自動認(rèn)證
從1.0.0版本之后,docker-maven-plugin插件會自動讀取到docker-cli的認(rèn)證配置,默認(rèn)在~/.dockercfg 和~/.docker/config.json,而無需額外的配置
GCR認(rèn)證
如果本機(jī)配置DOCKER_GOOGLE_CREDENTIALS的環(huán)境變量,則會使用GCR認(rèn)證。
Server認(rèn)證
也可以在maven的settings.xml配置認(rèn)證信息:
<servers>
<server>
<id>docker-hub</id>
<username>foo</username>
<password>secret-password</password>
<configuration>
<email>foo@foo.bar</email>
</configuration>
</server>
</servers>
在pom.xml則通過如下配置關(guān)聯(lián)上述server id
<plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>VERSION GOES HERE</version>
<configuration>
[...]
<serverId>docker-hub</serverId>
<registryUrl>https://index.docker.io/v1/</registryUrl>
</configuration>
</plugin>
</plugins>
以上三種配置方式中,通過讀取客戶端默認(rèn)配置的優(yōu)先級更高。
在server配置中加密密碼
為了不在配置文件中不暴露明文密碼,可以使用maven加密功能對密碼進(jìn)行加密,通過{ }方式都認(rèn)為是被加密的密碼
<servers>
<server>
<id>docker-hub</id>
<username>foo</username>
<password>{gc4QPLrlgPwHZjAhPw8JPuGzaPitzuyjeBojwCz88j4=}</password>
</server>
</servers>
注意
構(gòu)建的鏡像名稱不要含有SNAPSHOT,因?yàn)殓R像名稱只允許 [a-z0-9-_.]