Docker Maven Harbor

Maven插件构建Docker镜像并推送到镜像仓库

Posted on 2020-10-14,10 min read

Spotify官方已经不再推荐使用docker-maven-plugin,不在进行维护,转而推荐了另外一款由该公司开发的Maven插件dockerfile-maven-plugin。

今天我们就来介绍下如何使用该插件。

构建Docker镜像

  1. 配置pom.xml

首先,在pom.xml中引入dockerfile-maven-plugin插件,并配置该插件。

如果是镜像仓库Harbor,配置镜像仓库私服地址

<properties>
	<!--docker私服地址-->
	<docker.repostory>harbor.hngtrust.com</docker.repostory>
</properties>

如果是镜像仓库Docker Hub,配置镜像仓库私服地址

<properties>
	<!--docker私服地址-->
	<docker.repostory>docker.io</docker.repostory>
</properties>

增加dockerfile-maven-plugin的配置,以eureka为例:

<plugin>
	<groupId>com.spotify</groupId>
	<artifactId>dockerfile-maven-plugin</artifactId>
	<version>1.4.13</version>
	<executions>
		<execution>
			<id>harbor</id>
			<goals>
				<goal>build</goal>
				<goal>push</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<repository>${docker.repostory}/library/${project.artifactId}</repository>
		<tag>${project.version}</tag>
		<useMavenSettingsForAuth>true</useMavenSettingsForAuth>
		<username>admin</username>
		<password>Harbor12345</password>
		<buildArgs>
			<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
		</buildArgs>
	</configuration>
</plugin>

可以看到,该插件的配置比docker-maven-plugin更简单了。

repository指定docker镜像的repo名字。

tag指定docker镜像的tag。

buildArgs可以指定一个或多个变量,传递给Dockerfile,在Dockerfile中通过ARG指令进行引用。

另外,可以在execution中同时指定build和push目标。当运行mvn package时,会自动执行build目标,构建Docker镜像。当运行mvn deploy命令时,会自动执行push目标,将Docker镜像push到Docker仓库。

  1. 编写Dockerfile

该插件不像docker-maven-plugin插件那样,可以不用准备Dockerfile,而是通过配置pom,由插件自动生成Dockerfile,并使用生成的Dockerfile构建Docker镜像。

该插件要求必须提供Dockerfile文件,而且要求放在项目根目录下,即与pom.xml同级目录。然后不需要像docker-maven-plugin插件那样需要指定Dockerfile文件存放路径的dockerDirectory参数。

而且,使用该插件,有一个重要的功能是,我们可以在Dockerfile中以target开头的相对路径来引用maven构建的artifact,如jar包。

如下面的Dockerfile文件内容所示:

FROM java:8
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENV ACTIVE=""
ADD target/dhcc-eureka-server-0.1.1-SNAPSHOT.jar dhcc-eureka-server.jar
ENTRYPOINT ["java", "-jar","-Dspring.profiles.active=${ACTIVE}",  "/dhcc-eureka-server.jar"]

我们看到,在ADD指令后面,使用了以target开头的相对路径来引用maven构建的jar包。

另外,从上面的示例中还看到,我们使用了该插件提供的另外一个新功能。正如前面提到的在pom.xml里通过buildArgs指定的变量,可以在Dockerfile中通过ARG指令引用进来,ENV ACTIVE="" 然后就可以在Dockerfile的其他地方用${ACTIVE}的方式引用由pom.xml传递进来的变量值,可以实现不同环境启动。

  1. 构建Docker镜像

使用该插件构建Docker镜像,需要有一个安装好的Docker运行环境。

且需要在运行该插件的机器上定义DOCKER_HOST环境变量,配置访问Docker的URL,如下:

export DOCKER_HOST=tcp://localhost:2375

上面的例子,是在Linux环境下定义的DOCKER_HOST环境变量,因为Docker安装在本机上,因此使用localhost。如果你的Docker运行环境不在本机,请使用Docker所在机器的IP

2375是为Docker开启的远程访问API的端口,如果你开启的是其他端口,请使用具体的端口。如果你的Docker没有开启远程访问API,请自行Google开启。

如果你要在Windwos上运行该Maven插件,同样需要在Windows上配置DOCKER_HOST环境变量,值为:tcp://localhost:2375,就可以运行maven命令来构建Docker镜像了:

mvn package

mvn dockerfile:build

命令执行成功后,运行docker命令检查镜像是否存在:

docker images

推送Docker镜像

Docker镜像构建好后,我们还可以使用该插件将镜像推送到Docker仓库,如Docker Hub。

下面介绍如何推送到Docker Hub。

  1. 创建repository

首先,我们需要登录Docker Hub并创建一个repository,如下图所示,我们创建了config-server的repository:

  1. 配置pom.xml

docker hub 的repository的格式必须为:

/<repository_name>

<configuration>
  <repository>jwangkun/dhcc-eureka-server</repository>
  <tag>${project.version}</tag>
  <buildArgs>
    <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
  </buildArgs>
</configuration>

username就是登录Docker Hub的用户名,例如我的用户名是jwangkun, repository_name就是上一步在Docker Hub上创建的repository名字。

Harbor则在pom.xml中为该插件配置Docker镜像的repository名字,如下:

<configuration>
  <repository>${docker.repostory}/library/dhcc-eureka-server</repository>
  <tag>${project.version}</tag>
  <buildArgs>
    <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
  </buildArgs>
</configuration>

注意 :library为harbor仓库中创建的项目名称 ,${docker.repostory} 则为上面pom.xml 中properties配置的docker.repostory的值

  1. 配置认证

接下来,需要为插件配置认证信息,即登录Docker Hub的用户名和密码。因为插件在push镜像前,需要登录Docker Hub。

有三种方式配置认证信息。

第一种:在pom.xml中配置认证信息

如下所示,可以直接在pom.xml为插件配置usnername和password:

<configuration>
  <repository>jwangkun/dhcc-eureka-server</repository>
  <tag>${project.version}</tag>
  <username>jwangkun</username>
  <password>xxxx</password>
  <buildArgs>
    <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
  </buildArgs>
</configuration>

第二种:在settings.xml中配置server

如下所示,在maven的settings.xml中的servers下增加一个server配置:

对于Docker Hub,server.id必须是http://docker.io。

<servers>
  <server>
    <id>docker.io</id>
    <username>jwangkun</username>
    <password>xxxx</password>
  </server>
</servers>

对于Harbor,server.id必须是换成Harbor服务地址以及端口即可。

<servers>
	<server>
		<id>192.168.1.1:9001</id>
		<username>admin</username>
		<password>*****</password>
		<configuration>
			<email>******@qq.com</email>
		</configuration>
	</server>
</servers>

然后在pom.xml中指定useMavenSettingsForAuth为true:

<configuration>
  <repository>jwangkun/dhcc-eureka-server</repository>
  <tag>${project.version}</tag>
  <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
  <buildArgs>
    <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
  </buildArgs>
</configuration>

第三种:直接在mvn命令行上提供认证信息

如果没有在pom.xml中配置认证信息,也没有在settings.xml中配置认证信息,那么我们还可以简单地在运行的mvn命令行上以参数的形式提供认证信息,如下所示:

mvn dockerfile:push -Ddockerfile.username=jwangkun -Ddockerfile.password=xxxx

第一种方式,由于需要在pom.xml中配置用户密码,而pom.xml一般都会随着源码一起提交到版本控制系统中,因此有暴露用户密码的风险。

第三种方式,在每次运行maven命令时,都需要额外提供用户名和密码,比较麻烦。

因此,一般推荐使用第二种方式。

  1. push镜像

接下来,执行maven命令来push镜像。

对于前两种认证方式,我们可以直接运行mvn goal命令来push镜像:

mvn deploy

或者

mvn dockerfile:push

对于第三种认证方式,使用上面提到的命令来push镜像。

mvn dockerfile:push -Ddockerfile.username=jwangkun -Ddockerfile.password=xxxx

需要注意的是,如果你没有配置部署artifact的maven repository,请不要使用mvn deploy命令,因为它会执行maven-deploy-plugin的deploy目标,而由于没有配置要部署的远程maven repository,会报类似如下的错:

Deployment failed: repository element
was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter

在这种情况下,请使用下面的命令来push镜像:

mvn dockerfile:push
  1. 检查镜像maven命令执行成功后,可以登录Docker Hub来检查镜像是否存在。

推送镜像到Harbor仓库

由于我要推送的仓库是私有的,需要用户名密码,所以,要在maven的配置文件(setting文件)中,添加如下配置:

<configuration>
    <repository>${docker.repostory}/library/${project.artifactId}</repository>
    <tag>${project.version}</tag>
    <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
    <username>admin</username>
    <password>Harbor12345</password>
    <buildArgs>
    	<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
    </buildArgs>
</configuration>

注意如果是Harbor仓库,useMavenSettingsForAuth一定要加上,貌似在maven的settings.xml中的servers没有生效还是其他原因,会报地址错误或者用户名密码登录不上的情况,加上useMavenSettingsForAuth就可以了

 <useMavenSettingsForAuth>true</useMavenSettingsForAuth>

配置好之后,执行命令:

mvn dockerfile:push

下一篇: Kubernetes Ingress→