【CI/CD技术专题】「Docker实战系列」使用Maven插件构建Docker镜像的方法
本文介绍了使用Maven插件构建Docker镜像的方法,分享给大家,具体如下:
工具
工欲善其事,必先利其器。笔者经过调研,有以下几款Docker的Maven插件进入笔者视野。
插件名称+官方地址
-
docker-maven-plugin https://github.com/spotify/docker-maven-plugin
-
docker-maven-plugin https://github.com/fabric8io/docker-maven-plugin
-
docker-maven-plugin https://github.com/bibryam/docker-maven-plugin
修改宿主机配置(docker可以远程访问)
- 修改宿主机的docker配置,让其支持远程访问。
vi /usr/lib/systemd/system/docker.service
开启docker远程API,修改docker配置文件 docker.service进入编辑模式后。
ExecStart=后添加配置-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
保存后退出,重新加载配置文件#systemctl daemon-reload ,启动docker #systemctl start docker 。
- 刷新配置,重新服务
systemctl daemon-reload
systemctl restart docker
配置 DOCKER_HOST
docker-maven-plugin 插件默认连接本地 Docker 地址为:localhost:2375,所以我们需要先设置下环境变量。
DOCKER_HOST=tcp://<host>:2375
注意:如果没有设置 DOCKER_HOST 环境变量,可以命令行显示指定 DOCKER_HOST 来执行,如我本机指定 DOCKER_HOST:DOCKER_HOST=tcp://<host>:2375
例如
-
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock ,这里就写4个0,你可别改成自己的ip哦,
-
输入
#netstat -anp|grep 2375
显示docker正在监听2375端口,输入#curl 127.0.0.1:2375/info 显示一大堆信息,证明远程api就弄好了 -
在windows系统环境变量中新建DOCKER_HOST,值为tcp://10.100.74.220:2375,(你改成你自己的docker服务器ip地址)
使用插件构建Docker镜像
在我们持续集成过程中,项目工程一般使用 Maven 编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便。docker-maven-plugin 插件就是为了帮助我们在Maven工程中,通过简单的配置,自动生成镜像并推送到仓库中。
添加插件
在pom.xml中添加下面这段:
<build>
添加相关的镜像插件
</build>
构建镜像
构建镜像可以使用一下两种方式,第一种是将构建信息指定到 POM 中,第二种是使用已存在的 Dockerfile 构建。(支持将 FROM, ENTRYPOINT, CMD, MAINTAINER 以及 ADD 信息配置在 POM 中,不需要使用 Dockerfile 配置。)
-
第一种方式,支持将 FROM, ENTRYPOINT, CMD, MAINTAINER 以及 ADD 信息配置在 POM 中,不需要使用 Dockerfile 配置
-
第二种方式,如果使用 VOLUME 或其他 Dockerfile 中的命令的时候,需要创建一个 Dockerfile,并在 POM 中配置 dockerDirectory 来指定路径即可。(创建一个 Dockerfile,并在 POM 中配置 dockerDirectory 来指定路径即可)
添加docker-maven-plugin
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<imageName>{dockerhub名称/imageName}</imageName>
<imageTags>
<imageTag>{imageTag}</imageTag>
</imageTags>
<baseImage>{baseImage}</baseImage>
<entryPoint>{end[point]}</entryPoint>
<maintainer>author author@email.com</maintainer>
<workdir>/ROOT</workdir>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
-
{dockerhub名称/imageName}:
-
dockerhub名称:对应DockerHub用户名,,一定要是符合正则[a-z0-9-_.]的,否则构建不会成功
-
imageName:对应 DockerHub 仓库名,一定要是符合正则[a-z0-9-_.]的,否则构建不会成功
-
可以直接指定:${project.groupId}/${project.artifactId}
-
-
{imageTag}:镜像标签,相当于标签或者版本,latest。
-
{baseImage}: 指定基础镜像,等同 FROM 指令,例如:java,当然可以不用,直接在dockerfile文件中生成。
-
{endpoint}:// 等同于 ENTRYPOINT 指令,例如: ["java","-jar","app.jar"]
这里是复制 jar 包到 docker 容器指定目录配置,也可以写到 Dockerfile中
-
{project.build.directory}:指定要复制的根目录,${project.build.directory} 表示 target 目录。
-
{project.build.finalName}:指定要复制的文件,${project.build.finalName}.jar 指打包后的 jar 文件。
-
resources.resource.targetPath:将打包后的资源文件复制到该目录;
-
resources.resource.directory:需要复制的文件所在目录,maven打包的应用jar包保存在target目录下面;
-
resources.resource.include:需要复制的文件,打包好的应用jar包。
读取 Dockerfile 文件就不必指定 baseImage 和 entrypoint
- 指定要读取的Dockerfile文件:
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
创建Dockerfile
\src\main\docker
内容如下
FROM java:8
VOLUME /tmp
ADD admin-service-80-0.0.1-SNAPSHOT.jar admin-service-80.jar
RUN bash -c 'touch /admin-service-80.jar'
EXPOSE 80
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","${project.build.finalName}.jar"]
执行以下命令构建 Docker 镜像
mvn clean package docker:build
[INFO] --- docker-maven-plugin:1.0.0:build (default-cli) @ mavenDemo ---
[INFO] Building image mavendemo
Step 1/5 : FROM java
---> d23bdf5b1b1b
Step 2/5 : MAINTAINER docker_maven docker_maven@email.com
---> Using cache
---> 2faf180d4a50
Step 3/5 : WORKDIR /ROOT
---> Using cache
---> 862210f7956a
Step 4/5 : ENTRYPOINT java -jar mavenDemo.jar
---> Running in 96bbe83de6ec
---> c29009c88993
Removing intermediate container 96bbe83de6ec
Step 5/5 : CMD java -version
---> Running in f69b8d2a75b1
---> bc8d54014325
Removing intermediate container f69b8d2a75b1
Successfully built bc8d54014325
执行 docker images 查看刚才构建的镜像
执行命令
- mvn clean package docker:build:只执行 build 操作
- mvn clean package docker:build -DpushImage 执行 build 完成后 push 镜像
- mvn clean package docker:build -DpushImageTag 执行 build 并 push 指定 tag 的镜像
注意:这里必须指定至少一个 imageTag,它可以配置到POM 中,也可以在命令行指定。
命令行指定如下:
mvn clean package docker:build -DpushImageTags -DdockerImageTags=imageTag_1 -DdockerImageTags=imageTag_2,POM 文件中指定配置如下:
<build>
<plugins>
...
<plugin>
<configuration>
...
<imageTags>
<imageTag>imageTag_1</imageTag>
<imageTag>imageTag_2</imageTag>
</imageTags>
</configuration>
</plugin>
...
</plugins>
</build>
绑定Docker 命令到 Maven 各个阶段
-
可以绑定 Docker 命令到 Maven 各个阶段,我们可以把 Docker 分为 build、tag、push,然后分别绑定 Maven 的 package、deploy 阶段。
-
只需要执行mvn deploy就可以完成整个 build、tag、push操作了,当我们执行mvn build就只完成 build、tag 操作。
-
除此此外,当我们想跳过某些步骤或者只执行某个步骤时,不需要修改 POM 文件,只需要指定跳过 docker 某个步骤即可。比如当我们工程已经配置好了自动化模板了,但是这次我们只需要打镜像到本地自测。
-
不想执行 push 阶段,那么此时执行要指定参数-DskipDockerPush就可跳过 push 操作了。
以上示例,当我们执行mvn package时,执行 build、tag 操作,当执行mvn deploy时,执行build、tag、push 操作。如果我们想跳过 docker 某个过程时,只需要:
- -DskipDockerBuild 跳过 build 镜像
- -DskipDockerTag 跳过 tag 镜像
- -DskipDockerPush 跳过 push 镜像
- -DskipDocker 跳过整个阶段
例如:我们想执行 package 时,跳过 tag 过程,那么就需要mvn package -DskipDockerTag。
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>mavendemo</imageName>
<baseImage>java</baseImage>
<maintainer>docker_maven docker_maven@email.com</maintainer>
<workdir>/ROOT</workdir>
<cmd>["java", "-version"]</cmd>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/ROOT</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</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>mavendemo:latest</image>
<newName>docker.io/wanyang3/mavendemo:${project.version}</newName>
</configuration>
</execution>
<execution>
<id>push-image</id>
<phase>deploy</phase>
<goals>
<goal>push</goal>
</goals>
<configuration>
<imageName>docker.io/wanyang3/mavendemo:${project.version}</imageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
docker-maven-plugin 插件还提供了很多很实用的配置,稍微列举几个参数吧。
安全认证配置
当我们 push 镜像到 Docker 仓库中时,不管是共有还是私有,经常会需要安全认证,登录完成之后才可以进行操作。当然,我们可以通过命令行
docker login -u user_name -p password docker_registry_host
登录,但是对于自动化流程来说,就不是很方便了。使用 docker-maven-plugin 插件我们可以很容易实现安全认证。
首先在 Maven 的配置文件 setting.xml 中增加相关 server 配置,主要配置 Docker registry用户认证信息。
<servers>
<server>
<id>my-docker-registry</id>
<username>wanyang3</username>
<password>12345678</password>
<configuration>
<email>wanyang3@mail.com</email>
</configuration>
</server>
</servers>
然后只需要在 pom.xml 中使用 server id 即可。
<plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>registry.example.com/wanyang3/mavendemo:v1.0.0</imageName>
...
<serverId>my-docker-registry</serverId>
</configuration>
</plugin>
使用私有Docker仓库地址
实际工作环境中,我们需要 push 镜像到我们私有 Docker 仓库中,使用d ocker-maven-plugin 插件我们也是很容易实现,有几种方式实现:
修改 POM 文件 imageName 操作
<configuration>
<imageName>{privateImageHubUrl}/imageName/tag</imageName>
...
</configuration>
以以上的格式进行输出即可。
修改 POM 文件中 newName 操作
<configuration>
<imageName>mavendemo</imageName>
...
</configuration>
<execution>
<id>tag-image</id>
<phase>package</phase>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<image>mavendemo</image>
<newName>{privateImageHubUrl}/imageName/tag</newName>
</configuration>
</execution>
重新启动Docker服务
systemctl stop docker
systemctl start docker
开启防火墙的Docker构建端口
firewall-cmd --zone=public --add-port=2375/tcp --permanentfirewall-cmd --reload

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
面对大规模 K8s 集群,这款诊断利器必须要“粉一波”!
作者|段超 来源|尔达 Erda 公众号 背景 我们是一家做商业软件的公司,从一开始我们就把软件交付流程做的非常标准且简单,所有的软件都是基于我们的企业数字化平台 Erda(现已开源)来交付,底层基于 Kubernetes,为企业提供 DevOps、微服务治理、多云管理以及快数据管理等云厂商无绑定的 IT 服务。 随着我们服务的客户数量越来越多,如今我们管理着相当规模数量的 Kubernetes 集群,集群的稳定性决定了服务质量以及对外口碑,很长一段时间内我们在这件事情上都显得很被动,经常会出现 Erda 支持同学或者客户将问题反馈到我们说:有业务出现了问题,需要我们协助查询一下是不是平台导致的,然后我们上去一顿操作最后解决问题,答复客户。看似专业且厉害,急用户之所急,实则无章无法,一地鸡毛。 通常我们依赖监控系统来提前发现问题,但是监控数据作为一个正向链路,很难覆盖到所有场景,经常会有因为集群配置的不一致性或者一些更底层资源的异常,导致即使监控数据完全正常,但是整个系统依然会有一些功能不可用。对此,我们做了一套巡检系统,针对系统中一些薄弱点以及一致性做诊断,美中不足的是,这套系统...
-
下一篇
延迟执行与不可变,系统讲解JavaStream数据处理
最近在公司写业务的时候,忽然想不起来Stream中的累加应该怎么写? 无奈只能面向谷歌编程,花费了我宝贵的三分钟之后,学会了,很简单。 自从我用上JDK8以后,Stream就是我最常用的特性,各种流式操作用的飞起,然而这次事以后我忽然觉得Stream对我真的很陌生。 可能大家都一样,对最常用到的东西,也最容易将其忽略,哪怕你要准备面试估计也肯定想不起来要看一下Stream这种东西。 不过我既然注意到了,就要重新梳理一遍它,也算是对我的整体知识体系的查漏补缺。 花了很多功夫来写这篇Stream,希望大家和我一块重新认识并学习一下Stream,了解API也好,了解内部特性也罢,怕什么真理无穷,进一步有进一步的欢喜。 在本文中我将Stream的内容分为以下几个部分: 初看这个导图大家可能对转换流操作和终结流操作这两个名词有点蒙,其实这是我将Stream中的所有API分成两类,每一类起了一个对应的名字(参考自Java8相关书籍,见文末): 转换流操作 :例如filter和map方法,将一个Stream转换成另一个Stream,返回值都是Stream。 终结流操作 :例如count和collec...
相关文章
文章评论
共有0条评论来说两句吧...