我看了很多关于idea一键打包docker镜像并推送harbor仓库的文章,不论国内国外的,基本上99%都是瞎写的, 这些人不清楚打包插件原理,然后就是复制粘贴一大篇,写了一堆垃圾,然后别人拿来也不能用。
然后这篇文章是经过我无数次测试、踩坑后得出宝贵经验,然后在此分享给各位!
首先谈第一个问题: idea的docker插件不是必须安装的!
我看了那么多傻吊写的文章:在maven插件里面配了一大堆的harbor仓库的认证信息,结果
mvn clean package 以后,发现只能打包docker镜像没有push推送成功!
也就是:你要推送镜像还得使用docker插件, 总共需要两步才能完成docker镜像的打包和推送!
像下面这样:
这他妈叫一键推送吗?!
所以我发誓一定要研究出一套真正意义上的idea一键打包推送docker镜像的方法。
我这里提供com.spotify和io.fabric8两种方法,是绝对可以使用的。
两种方法都需要开启docker 2375端口.
注意:远程docker和远程harbor仓库是两个概念:
因为你打包docker镜像和push推送都需要一个docker程序,而idea需要一个能远程控制docker的机制,这就是开启远程docker 2375端口的原因。
而远程harbor仓库,说白了就是你打包后docker镜像存储的地方,仅此而已。
关于搭建harbor仓库的方法可以参看我的一篇文章: centos搭建docker镜像Harbor仓库的简明方法-CSDN博客
开启远程docker 2375端口的方法有两种:
1. 在/etc/docker/daemon.json文件中加入:
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"] 然后重启docker
第二种方法:编辑/usr/lib/systemd/system/docker.service文件
在ExecStart=/usr/bin/dockerd 后面增加 -H tcp://0.0.0.0:2375
然后运行命令:
systemctl daemon-reload
systemctl restart docker
以上是准备工作,现在开始说正题。
首先谈第一种方法: com.spotify出品的dockerfile-maven-plugin插件,
pom.xml核心配置如下:
<properties>
<!-- docker镜像的版本号 -->
<image.tag.verion>v1.0.1</image.tag.verion>
<!-- 远程harbor仓库的域名地址 -->
<docker.repostory>harbor.myhub.com</docker.repostory>
</properties>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<executions>
<execution>
<id>default</id>
<!-- maven打包阶段就触发dockerfile-maven-plugin插件的以下动作 -->
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>tag</goal>
<goal>push</goal>
</goals>
<configuration>
<!-- 给docker镜像打上版本号 -->
<tag>${image.tag.verion}</tag>
</configuration>
</execution></executions>
<configuration>
<!-- 指定dockerfile所在目录 -->
<contextDirectory>${project.basedir}</contextDirectory>
<!-- 指定docker镜像名,格式必须这样写, 注意:这里${docker.repostory}仓库地址必须有,因为docker需要这个去连接你真实仓库地址,否则就会连接到官方的docker.io仓库了, 镜像名称格式是:harbor仓库域名/子仓库/镜像名称,版本号由上面的tag动作标注 -->
<repository>${docker.repostory}/library/${project.artifactId}</repository>
<!-- 连接远程harbor仓库的用户名和密码 -->
<username>admin</username>
<password>Harbor12345</password>
<!-- 传递环境变量:JAR_FILE给dockerfile -->
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs></configuration>
</plugin>
这里有个特别需要注意地方:repository标签,也就是push到harbor仓库的镜像名称,
必须是这种格式: harbor仓库域名/子仓库/镜像名称
如果不这样写: 就会推送到官方docker.io仓库!
另外需要在IDEA的maven中配置DOCKER_HOST环境变量:
这个DOCKER_HOST是指安装有docker的机器,并且需要开启2375端口。
不建议在本地windows安装docker,因为它本质上还是搞一个虚拟机跑docker,没必要。
然后是dockerfile的内容:
FROM openjdk:8-jdk-alpine ARG JAR_FILE # 接收pom.xml文件传递的变量 # 注意WORKDIR指向的目录必须提前存在,否则后面复制文件的时候会失败,导致容器无法运行 RUN echo "JAR_FILE is: ${JAR_FILE}" && mkdir /app WORKDIR /app COPY target/${JAR_FILE} ./app.jar RUN echo "ls result" && ls -l /app ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
注意点:
1. WORKDIR指向的目录必须提前存在,否则后面复制文件的时候会失败,导致容器无法运行, 会报错:Error: Invalid or corrupt jarfile app.jar.
原因:WORKDIR 指令是设置工作目录,但并不会在文件系统中创建目录。
2. 同时,这里通过pom 文件的buildArgs标签传递JAR_FILE变量,然后在dockerfile里面通过ARG JAR_FILE来接收变量,目的是不把idea打包的jar文件名写死,实现动态化传参
3. 第三点:dockerfile必须放在当前项目的根目录,也就是pom文件的同级目录,如果不这样,那么dockerfile执行COPY指令时就需要使用COPY ../target/${JAR_FILE} ./app.jar, 因为COPY指令的路径是dockerfile所在路径,如果dockerfile在子目录,就必须向外层寻找jar文件的构建目录也就是target目录
4. pom文件中的项目最顶层的artifactId必须是小写,否则docker镜像构建不能成功,会报错:xxx must contain only lowercase, numbers, '-', '_' or '.'.
第二种方法:io.fabric8出品的docker-maven-plugin插件
io.fabric8不需要在IDEA配置DOCKER_HOST环境变量,因为它在pom文件中有自带dockerHost字段,能够指定远程docker地址。
pom.xml核心配置如下:
<properties><!-- docker镜像的版本号 --><image.tag.verion>v1.0.1</image.tag.verion><!-- 远程harbor仓库的域名地址 --><docker.repostory>harbor.myhub.com</docker.repostory>
</properties> <plugin><groupId>io.fabric8</groupId><artifactId>docker-maven-plugin</artifactId><version>0.43.4</version><executions><execution><id>default</id><!--用户只需执行mvn package ,就会自动执行mvn docker:build/push动作--><phase>package</phase><goals><goal>build</goal><goal>push</goal></goals></execution></executions><configuration><!-- 指定远程habor仓库的域名地址 --><registry>${docker.repostory}</registry><authConfig><!-- 指定远程habor仓库的登录用户名和密码 --><username>admin</username><password>Harbor12345</password></authConfig><images> <image><!-- --指定生成的镜像名, 必须这样写, 注意:这里${docker.repostory}仓库地址必须有,因为docker需要这个去连接你真实仓库地址,否则就会连接到官方的docker.io仓库了,镜像名称格式是:harbor仓库域名/子仓库/镜像名称:版本号 --><name>${docker.repostory}/library/${project.artifactId}:${image.tag.verion}</name><build><!-- 指定dockerfile所在的目录 --><contextDir>${project.basedir}</contextDir></build></image></images><!--指定远程 docker daemon地址--><dockerHost>http://192.168.10.30:2375</dockerHost><!-- 传递环境变量:JAR_FILE给dockerfile --><buildArgs><JAR_FILE>${project.build.finalName}.jar</JAR_FILE></buildArgs></configuration></plugin>
然后dockerfile也是必须在项目根目录,内容跟上面的一样。
最后使用maven测试一下docker镜像的打包和推送功能:
以上已经成功验证了idea一键打包docker镜像并推送到harbor仓库