我们在用Spring Cloud开发微服务时,往往会使用Maven来管理项目并打包成jar文件,最后往往也需要把jar文件进一步构建成Docker镜像,从而可以在Docker容器中运行微服务。
那么有没有一种自动构建Docker镜像的方法呢?
这是一个非常常见的需求,因此大佬们早就已经为我们开发了Maven插件来自动完成这个工作。
实际上已经有不止一款类似的插件,但本文将只介绍用得最多一款:spotify公司开发的docker-maven-plugin插件。
下面我们来详细探讨如何使用Maven插件构建Docker镜像。
2
使用简单配置方式
假如我们开发了一个account-service的微服务。
1. 添加docker-maven-plugin插件
在项目的pom.xml文件中配置插件:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>account-service:1.0</imageName>
<baseImage>java</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
这是该插件的简单使用方式的配置,需要在pom.xml里配置以下配置项:
-
imageName
:用于指定镜像名称,分号后面的1.0是标签名称。 -
baseImage
:用于指定基础镜像,等同于Dockerfile中的FROM指令。 -
entrypoint
:类似于Dockerfile的ENTRYPOINT指令,代表运行镜像时执行的指令。 -
resources.resource.directory
:用于指定需要复制的文件的根目录,${project.build.directory}表示target目录。 -
resources.resource.include:
用于指定需要复制的文件。${project.build.finalName}.jar指的是maven编译打包后的jar包。
2. 构建Docker镜像
在项目的根目录(pom.xml的同级目录)执行以下命令:
mvn clean package docker:build
Maven的日志会输出类似于如下的内容:
[INFO] Building image account-service:1.0
Step 1 : FROM java
---> 861e95c114d6
Step 2 : ADD /acount-service-1.0.jar //
---> 035a03f5b389
Removing intermediate container 2b0e70056f1d
Step 3 : ENTRYPOINT java -jar /acount-service-1.0.jar
---> Running in a0149704b949
---> eb96ca1402aa
Removing intermediate container a0149704b949
Successfully built eb96ca1402aa
可以看到,我们已成功构建了Docker镜像。
执行如下命令,即可查看刚刚构建的镜像。
docker images
输出如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
account-service 1.0 eb96ca1402aa 39 seconds ago 685 MB
可以看到,镜像已经存在了。
3. 运行镜像
我们可以运行镜像来测试一下我们的服务是否可以正常工作
docker run -d -p 8080:8080 account-service:1.0
我们会发现该Docker镜像会很快地启动
4. 测试服务
在Chrome上使用Postman插件发送rest请求到我们的服务地址http://<host>:8080/v1/account-service/account/<id>,测试是否可以正常访问并获取服务的响应。
注意:以上是我的服务的url,请根据你在spring中配置的url进行访问。
3
使用Dockerfile方式
之前的示例中,我们直接在pom.xml中设置了一些参数,但插件支持的配置参数是比较有限的。而在实际项目开发中,大部分情况下需要通过编写Dockerfile来构建镜像。
该插件当然也支持这种方式。
1. 编写Dockerfile
我们可以在account-service/src/main目录下创建一个docker 目录下,在下面新建一个Dockerfile文件,例如:
FROM java:8
ADD account-service-1.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
2. 修改pom.xml
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>account-service:1.0</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
可以看到,pom的配置变得简单了,我们不需要再指定baseImage和entryPoint,这些信息都转移到Dockerfile文件里了,而我们只需要使用dockerDirectory指定Dockerfile所在的路径即可。
这样,我们就可以使用Dockerfile构建Docker镜像了。只需要运行同样的maven打包命令:
mvn clean package docker:build
4
绑定到某个phase来构建Docker镜像
如果我们希望简化maven打包命令,想要在执行例如mvn clean package 时,插件就被自动执行,并为我们构建Docker镜像。
要想实现这点,我们只需将插件的goal绑定在某个phase即可。
比如,我们可以将插件的build目标绑定到package打包阶段。build 目标表示使用maven插件构建Docker镜像的goal,package phase表示使用maven编译并打包jar文件的阶段。也就是说在maven编译打包jar文件后,立即执行插件的build目标来构建Docker镜像。
配置如下:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<executions>
<execution>
<id>build-docker-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<imageName>account-service:1.0</imageName>
<baseImage>java</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
由配置可知,我们只需添加如下配置:
<executions>
<execution>
<id>build-docker-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
有了上面的配置,我们可以简单的执行以下命令,Maven就可以为我们自动编译打包成jar文件,并自动构建Docker镜像。
mvn clean package
5
推送镜像到Docker仓库
我们也可使用这个Maven插件来自动将构建好的镜像push到Docker仓库,如Docker Hub。
首先需要在maven的setttings.xml文件中配置访问Docker Hub server的用户信息。
<server>
<id>docker-hub</id>
<username>Docker Hub用户名</username>
<password>Docker Hub密码</password>
<configuration>
<email>Docker Hub邮箱</email>
</configuration>
</server>
然后修改pom.xml,示例:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>account-service:1.0</imageName>
<baseImage>java</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<!-- 必须与maven配置文件settings.xml中配置的server.id一致 -->
<serverId>docker-hub</serverId>
</configuration>
</plugin>
如上,添加serverId段落,并引用settings.xml中的server的id即可。
这样就配置好了。但需要注意,我们在执行maven命令时,需要添加pushImage的标识,才会自动push镜像。如下所示:
mvn clean package -DpushImage