概述
本文的目标是,使用docker-maven-plugin插件将spring boot工程打包成镜像并推送到华为云的容器仓库中。涉及到docker的API远程访问、华为云的容器仓库配置、docker-maven-plugin插件的使用等等。
华为云Docker仓库权限
创建IAM子账号
在远程使用docker客户端登录到华为云的时候,不要使用系统级权限账户。需要新建一个可在编程中使用IAM用户。


由于是子账户,只需要输入用户名。如果只是push镜像使用,可以将【控制台访问】的选择去掉。

在本页中,如果你使用用户组来管理权限,那么请正常选择组就可以了,如果没有直接点击创建用户即可。

点击确认,将访问密钥下载并小心保存起来,下面我们还会用到。
创建组织(镜象服务)并授权
输入组织名称:dokbok,下面的项目配置中会用到这个组织名。

为组织添加用户授权


到这里,我们在华为云的控制台操作已经完成。下面我们需要将IAM的账号转换成docker类型的用户及密码。
转换账号及密码
上面我们在创建IAM用户的时候得到了一对Key,

如下:
Access Key Id:DSB0AA……LFQSIK
Secret Access Key:F0BGD0v5……bzS6stcsgamFo8gxWk
本人使用的是Linux操作系统,下面的命令都是运行在Linux操作系统下的。
#printf "$AK" | openssl dgst -binary -sha256 -hmac "$SK" | od -An -vtx1 | sed 's/[ \n]//g' | sed 'N;s/\n//'
#将上面的命令的#AK换成上面的Access Key Id,将上面命令的$SK换成Secret Access Key,造成如下命令:
printf "DSB0AA……LFQSIK" | openssl dgst -binary -sha256 -hmac "F0BGD0v5……bzS6stcsgamFo8gxWk" | od -An -vtx1 | sed 's/[ \n]//g' | sed 'N;s/\n//'
输出:c17dba9……993a939e6
上面得到的字符串c17…9e6就是登录docker仓库所需要的密码。
使用Access Key ID作为用户名及上面printf…命令生成的密码,登录到华为云仓库进行测试:
docker login -u cn-north-4@[Access Key ID] -p [Password] swr.cn-north-4.myhuaweicloud.com
#cn-north-4是服务所在区,swr.cn-north-4.myhuaweicloud.com是所在区的华为云仓库的地址,具体请参见华为云帮助
docker login -u cn-north-4@DSB0AA……LFQSIK -p c17dba9……993a939e6 swr.cn-north-4.myhuaweicloud.com
如果显示登录成功(输出Login Succeeded),说明配置准确,后续配置pom.xml的时候会再次用到用户名及密码。
开启docker远程API访问端口
使用docker-maven-plugin插件来编译spring boot的相关工程并且推送到仓库,其过程还是需要Docker环境来支撑的。只是这个Docker环境是以远程调用的方式提供的。那么,如何开启Docker主机的远程API访问,请参见文章:Docker开启远程API端口
docker-maven-plugin插件配置及Dockerfile
1、多模块编译规则
尽可能在每个module中配置dockerfile及docker-maven-plugin的配置。因为按照微服务的理论,每一个module都会对应一个独立的功能,那么部署的过程中对外的端口等都会不同。目录如下:

2、父项目的pom配置
主要是为了配置docker-maven-plugin插件的版本管理。
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.40.1</version>
</plugin>
</plugins>
</pluginManagement>
</build>
3、子项目的pom配置
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<includeSystemScope>true</includeSystemScope>
<!--指定主类-->
<mainClass>com.bytebirth.shopstar.user.UserApplication</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<!--全局配置-->
<configuration>
<!--配置远程docker守护进程url-->
<dockerHost>https://192.168.3.10:2375</dockerHost>
<certPath>../dockerCerts</certPath>
<!--认证配置,用于私有registry认证-->
<authConfig>
<username>cn-north-4@DSG0NJLQFSIK</username>
<password>c17dba114645df612a3d03cc377c170ba939e6</password>
</authConfig>
<!--镜像相关配置,支持多镜像-->
<images>
<!-- 单个镜像配置 -->
<image>
<!--镜像名(含版本号)-->
<name>bytebirth/${project.name}:${project.version}</name>
<!--registry地址,用于推送,拉取镜像-->
<registry>swr.cn-north-4.myhuaweicloud.com</registry>
<!--镜像build相关配置-->
<build>
<!--使用dockerFile文件-->
<dockerFile>${project.basedir}\Dockerfile</dockerFile>
</build>
<run>
<ports>
<port>8080:8080</port>
</ports>
</run>
</image>
</images>
<buildArgs>
<!-- dockerfile参数,指定jar路径 -->
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
<executions>
<execution>
<id>docker:build</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<execution>
<id>docker:start</id>
<phase>install</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
其中下面的这个部分是用于编定maven的相关命令,如执行package的时候,同时执行docker:build;执行mvn install的时候,执行docker:start。可以在日常配置中去掉,我们可能打包的时候并不想推镜像。
<executions>
<execution>
<id>docker:build</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<execution>
<id>docker:start</id>
<phase>install</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
4、Dockerfile内容
FROM openjdk:18-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
编译
注意:在maven编译的配置中,Working directory一定要指定子项目的路径。

由于在docker-maven-plugin已经配置了docker与maven相关的生命周期,所以正常使用编译命令即可
#编译并运行
maven clean install
#只打包并发布镜像到华为云
maven clean package docker:push