一、docker-maven-plugin

docker-maven-plugin是一个用于构建和推送Docker镜像的Maven插件,该插件的官方文档地址如下:

https://github.com/spotify/docker-maven-plugin

但是从官网说明已经可以看出目前已经不再推荐使用这个插件,它推荐我们使用另外一个插件dockerfile-maven-plugin”。 

Spring Boot与Docker整合的官方文档地址如下:

https://spring.io/guides/topicals/spring-boot-docker/

二、dockerfile-maven-plugin插件的介绍

dockerfile-maven-plugin目前这款插件非常成熟,它集成了Maven和Docker,该插件的官方文档地址如下:

https://github.com/spotify/dockerfile-maven

其设计目标:

  • dockerfile是用来构建Docker项目的,这也是该插件所使用的,它们是强制性的。
  • 将Docker构建过程集成到Maven构建过程中。如果你绑定了默认阶段,当你输入 mvn package 命令时,你将得到一个Docker镜像;当你输入 mvn deploy 命令时,该镜像将会被推送。
  • 在pom.xml文件中使用goals标签声明我们想要做什么。这个里面的配置就相当于我们输入了 mvn dockerfile:build 命令后,再输入 mvn dockerfile:tag 命令,接着再输入 mvn dockerfile:push 命令。

该插件需要Java 7或更高版本和Apache Maven 3或更高版本(dockerfile-maven-plugin <= 1.4.6 需要Maven >= 3,其它情况需要Maven >= 3.5.2)。在实践中要运行集成测试或者使用该插件,需要一个Docker运行环境。

三、dockerfile-maven-plugin插件的配置

当前Maven版本为3.6.1,dockerfile-maven-plugin插件的版本为1.4.7!

以下这些配置步骤全都是基于dockerfile-maven-plugin插件:

第一步:在Maven的配置文件(settings.xml)中找到pluginGroups标签对,这个标签对的作用是“我们可以在这个地方指定用于插件查找的另一个组标识符” 

为了使用dockerfile-maven-plugin这个插件,因此要在这个标签对中新增下述这么一组配置:

<pluginGroups>
    <pluginGroup>com.spotify</pluginGroup>
</pluginGroups>

第二步:在pom.xml文件的build标签对中新增一个plugin插件配置,如下所示 

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
			<artifactId>dockerfile-maven-plugin</artifactId>
			<version>1.4.7</version>
			<executions>
			    <execution>
				    <id>build-image</id>
                    <phase>package</phase>
					<goals>
						<goal>build</goal>
						<goal>push</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<repository>docker-registry:5000/${project.artifactId}</repository>
				<tag>latest</tag>
				<buildArgs>
					<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
				</buildArgs>
				<force>true</force>
			</configuration>
		</plugin>
	</plugins>
</build>

上述配置中的 execution 标签对定义的是执行任务信息,这里面包含了4个子标签:

  • id:该标签的值表示执行任务(execution)的名称,自己可以随便定义,尽量做到见名知义。
  • phase:该标签的值表示的是我们想在构建的生命周期的什么阶段来执行任务,其取值一般有package、install。有的配置文件中我看到没有配置这个标签,但是我个人觉得还是明确配置下比较好。
  • goals:这个标签对是用来包裹goal标签,可以配置多个goal标签。
  • goal:这个标签表示的是使用Docker具体想做的事情,当值为build时表示要使用jar包制作生成Docker镜像,当值为push时表示要把生成的Docker镜像推送到Docker镜像仓库。

对于parse标签也是可以不要配置的,如果没有配置的话,则对于goal是使用默认的阶段:

Maven对 项目构建(build)的过程 进行了抽象和定义,这个过程被称为构建的生命周期(lifecycle),生命周期由多个阶段(phase)组成,如上所示一个生命周期有clean、compile、package等多个阶段。

上述配置中的 configuration 标签对定义的是docker任务执行过程中所需的一些配置信息,这里面包含了5个子标签: 

repository:表示的是该镜像推送到docker远程镜像仓库时的目录地址,例如上述示例中配置的是“docker-registry:5000/${project.artifactId}”,其中“docker-registry:5000”表示的是远程镜像仓库的地址,“${project.artifactId}”表示的是在该镜像在镜像仓库中所存放的目录,这个配置在我们在使用docker进行打标签(tag)时会被使用到。

tag:表示的是该镜像在打标签时的版本号,取值可以为latest。

buildArgs:该标签用于声明配置构建参数,其里面一般存放一些子标签对,这个是为 docker build 命令而服务,在利用Dockerfile文件构建生成docker镜像时可以引用到这里所配置的参数信息。

JAR_FILE:该标签表示构建参数声明(buildArgs标签对)下某一个具体的配置信息,例如上述示例中配置的就是所在项目生成打包生成jar包后的相对路径。

force:该标签表示是否强制推送到docker远程镜像仓库,值为true表示是,值为false表示否。  

${project.artifactId}:该配置是项目坐标名称的引用,其引用源如下。

${project.build.finalName}:项目构建打包后的名称引用,其引用源如下。

  

当我们在项目中首次引入dockerfile-maven-plugin这个插件以后,在 D:\repos\com\spotify 目录下会新增许多相关的文件和依赖包,如下图所示:

第三步:在pom.xml文件的同级目录下创建一个名为 “Dockerfile” 的文件,一个项目所对应的Dockerfile文件里面的内容可能如下所示。

FROM openjdk:8-jre
MAINTAINER zhangsan
# 添加一些特殊的依赖项:例如将本地项目的target/lib目录下的依赖添加到容器的/usr/share/myservice/lib目录下
ADD target/lib /usr/share/myservice/lib
# JAR_FILE是一个引用变量,会引用到在pom.xml文件中所声明的值
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar
EXPOSE 8082
ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"]

四、dockerfile-maven-plugin插件使用报错 Connection refused: connect 

问题描述:例如当前我们将上述pom.xml中关于docker镜像打包的配置文件修改为如下所示(即在使用Maven插件进行打包时,仅仅只想生成docker镜像):

<build>
	<plugins>
		<plugin>
			<groupId>com.spotify</groupId>
			<artifactId>dockerfile-maven-plugin</artifactId>
			<version>1.4.7</version>
			<executions>
				<execution>
					<id>build-image</id>
					<phase>package</phase>
					<goals>
						<goal>build</goal>
					</goals>
				</execution>
			</executions>
			<configuration>
				<repository>docker-registry:5000/${project.artifactId}</repository>
				<tag>latest</tag>
				<buildArgs>
					<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
				</buildArgs>
				<force>true</force>
			</configuration>
		</plugin>
	</plugins>
</build>

接着点击下述package选项进行打包,结果发现项目打Jar包是可以的,已经生成了Jar包。

但是在生成docker镜像时报下述错误:

Caused by: com.spotify.docker.client.shaded.org.apache.http.conn.HttpHostConnectException: Connect to localhost:2375 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect 

解决方法:出现这个问题的原因是docker的默认设置中,没有暴露Daemon的TCP端口2375。当前是在Windows系统中使用docker,因此要进入 Docker Desktop 的Settings界面,单击左侧导航栏中的General,勾选“Expose daemon on tcp://localhost:2375 without TLS”,然后再重启 Docker Desktop

接着我们再点击package选项进行打包,这时在IDEA的控制台(console)中就会输出下述信息: 

那么这整个过程就是利用Dockerfile文件构建docker镜像的一个流程,这个流程中最后两点信息很重要:

  1. 构建docker镜像成功,接着它会进行一个打tag标签的操作
  2. 最后在标签打完以后,会将原docker镜像文件删除掉,只保留打了tag标签的镜像文件

因此在使用package选项进行打包并且打包成功以后,我们可以使用 docker images 命令去查看所对应的docker镜像文件!!! 

五、通过命令方式使用dockerfile-maven-plugin插件

第一步:在IDEA的Terminal中进入到某一个项目的根目录下面

第二步:然后执行 mvn dockerfile:build 命令

接着在IDEA的Terminal中就会输出下述信息:

这种使用maven命令生成镜像文件,也和前面通过使用package选项来生成镜像文件的流程是一样的。

另外需要注意的是,在执行 mvn dockerfile:build 命令前需要保证在target目录下已经打好Jar包,否则在构建镜像文件的过程中会报下述错误:

Caused by: com.spotify.docker.client.exceptions.DockerException: ADD failed: file not found in build context or excluded by .dockerignore: stat target/xxx-server-1.0.0.jar: file does not exist

六、原生mvn package命令执行报错问题

在IDEA的Terminal中执行mvn package时报错Failure to find com.xxx:xxx-common:jar:1.0.0 in http://192.168.1.56:8081/repository/maven-public/ was cached in the local repository,如下图所示:

我们当前需要打包的项目它的pom.xml文件中引入了下述4个项目,但是在进行 mvn package 时却说找不到这4依赖包,我查看了一下本地仓库(D:\repo)中的相关目录和文件,发现这些依赖项其实都已经在本地仓库中安装成功。

[WARNING] The POM for com.xxx:xxx-common:jar:1.0.0 is missing, no dependency information available
[WARNING] The POM for com.xxx:xxx-api:jar:1.0.0 is missing, no dependency information available
[WARNING] The POM for com.xxx:xxx-api:jar:1.0.0 is missing, no dependency information available
[WARNING] The POM for com.xxx:xxx-api:jar:1.0.0 is missing, no dependency information available

再继续看控制台报错情况,大体就是说在下述这个仓库地址中找不到这4个依赖Jar包。

http://192.168.1.56:8081/repository/maven-public/
The following artifacts could not be resolved: 
com.xxx:xxx-common:jar:1.0.0,
com.xxx:xxx-api:jar:1.0.0, 
com.xxx:xxx-api:jar:1.0.0, 
com.xxx:xxx-api:jar:1.0.0: 
Failure to find com.xxx:xxx-common:jar:1.0.0 in http://192.168.1.56:8081/repository/maven-public/ was cached in the local repository

解决方法:我们直接使用mvn命令时,它所依赖的配置主要是自己的配置文件(setting.xml)和当前项目的根目录下的pom.xml文件,与IDEA这个开发工具的一些配置是没有关系的,这也很好的说明了一个问题那就是为什么我们在IDEA中通过点击Maven区域的Lifecycle选项(例如前面的package选项)是可以完成相应的事情,但是在控制台直接输入mvn命令会出现许多意想不到的错误

有一个问题就是为什么会从这个192.168.1.56:8081仓库下去获取该项目所需要的依赖包了? 

答:这个其实是涉及到了maven仓库优先级问题,当前我只在settings.xml文件中配置了远程仓库地址,但是没有在localRepository标签中配置本地仓库的地址,因为是使用原生的maven命令,那么它就找不到我们的本地仓库,自然而然也就无法首先从本地仓库中去获取相关的依赖包。 

针对这个问题,那么我们只需要在settings.xml文件中的localRepository标签处配置好本地仓库的目录就可以解决。再次执行上述命令,果然一套操作下来行云流水,没有再出现上述错误!!!

这个问题之前困扰了我许久,一个问题出现了不必一定要立马解决,可以适当走曲线策略,说不准什么时候灵感和机遇来了,瞬间这个问题就不是问题,哈哈哈!!!

七、其它相关的maven原生命令

# 执行清除和安装阶段并且跳过测试
mvn clean install -DskipTests
# 打包时并进行docker镜像构建
mvn package dockerfile:build
# 部署
mvn deploy
# docker镜像构建成功以后推送到远程仓库,前提是已经打好jar包
mvn dockerfile:build dockerfile:push
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐