近期在用Jib插件将Java工程构建成Docker镜像,使用时遇到过一些小问题,今天对这些问题做个小结;

关于Jib插件

Jib是用于构建Docker镜像的Maven插件,其基本用法请参考《Docker与Jib(maven插件版)实战》一文;

全文概览

本文由以下几部分组成:

  1. 环境信息
  2. 源码下载
  3. 小结一:三种构建参数
  4. 小结二:镜像的时间问题
  5. 小结三:多次构建后,积累的无用镜像问题
  6. 小结四:提升构建速度
  7. 小结五:将jib与mvn构建的生命周期绑定
  8. 小结六:父子结构的maven工程如何构建

环境信息

  1. 操作系统:CentOS Linux release 7.6.1810
  2. docker:1.13.1
  3. jdk:1.8.0_191
  4. maven:3.6.0
  5. jib插件:1.3.0

源码下载

本次实战用到的源码是个简单的maven工程,可以从GitHub上下载本次实战的源码,地址和链接信息如下表所示:

名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议

这个git项目中有多个文件夹,本章的源码在hellojib文件夹下,如下图红框所示:

小结一:三种构建参数

对于一个已在pom.xml中配置了jib插件的java工程来说,下面是个标准的构建命令:

mvn compile jib:dockerBuild

注意上面的dockerBuild参数,该参数的意思是将镜像存入当前的镜像仓库,这样的参数一共有三种,列表说明:

参数名 作用
dockerBuild 将镜像存入当前镜像仓库,该仓库是当前docker客户端可以连接的docker daemon,一般是指本地镜像仓库
build 将镜像推送到远程仓库,仓库位置与镜像名字的前缀有关,一般是hub.docker.com,使用该参数时需要提前登录成功
buildTar 将镜像生成tar文件,保存在项目的target目录下,在任何docker环境执行 docker load --input xxx.tar即可导入到本地镜像仓库

小结二:镜像的时间问题

在使用命令mvn compile jib:dockerBuild构建本地镜像时,会遇到创建时间不准的问题:
如下所示,bolingcavalry/hellojib是刚刚使用jib插件构建的镜像,其生成时间(CREATED字段)显示的是49 years ago:

[root@maven hellojib]# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
bolingcavalry/hellojib   0.0.1-SNAPSHOT      ef96fdd4473a        49 years ago        505 MB

上面显示的镜像生成时间显然是不对的,改正此问题的方法是修改pom.xml,在jib插件的container节点内增加useCurrentTimestamp节点,内容是true,如下所示:

<plugin><groupId>com.google.cloud.tools</groupId><artifactId>jib-maven-plugin</artifactId><version>1.3.0</version><configuration><!--from节点用来设置镜像的基础镜像,相当于Docerkfile中的FROM关键字--><from><!--使用openjdk官方镜像,tag是8-jdk-stretch,表示镜像的操作系统是debian9,装好了jdk8--><image>openjdk:8u212-jdk-stretch</image></from><to><!--镜像名称和tag,使用了mvn内置变量${project.version},表示当前工程的version--><image>bolingcavalry/hellojib:${project.version}</image></to><!--容器相关的属性--><container><!--jvm内存参数--><jvmFlags><jvmFlag>-Xms4g</jvmFlag><jvmFlag>-Xmx4g</jvmFlag></jvmFlags><!--要暴露的端口--><ports><port>8080</port></ports><!--使用该参数将镜像的创建时间与系统时间对其--><useCurrentTimestamp>true</useCurrentTimestamp></container></configuration></plugin>

修改保存后再次构建,此时新的镜像的创建时间已经正确,显示15 seconds ago:

[root@maven hellojib]# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
bolingcavalry/hellojib   0.0.1-SNAPSHOT      ee5ba19a8016        23 seconds ago      505 MB
<none>                   <none>              ef96fdd4473a        49 years ago        505 MB

小结三:多次构建后,积累的无用镜像

如下所示,构建多次后,本地会遗留多个名为<none>,tag也是<none>的镜像:

[root@maven hellojib]# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED              SIZE
bolingcavalry/hellojib   0.0.1-SNAPSHOT      a9fd91d8ad8c        17 seconds ago       505 MB
<none>                   <none>              a0cadeb9febd        About a minute ago   505 MB
<none>                   <none>              ee5ba19a8016        2 minutes ago        505 MB
<none>                   <none>              ef96fdd4473a        49 years ago         505 MB

这些都是上一次构建的结果,在经历了新一轮的构建后,其镜像名和tag被新镜像所有,所以自身只能显示名为<none>,tag也是<none>,清理这些镜像的命令是docker image prune,然后根据提示输入"y",镜像即可被清理:

[root@maven hellojib]# docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:7aa104e20b8a08bac3255f2627ac90f10021c6630370ce7a84ba33f89404b153
deleted: sha256:7dd7376ae00c2df0411bac1eded4b3c79dd1528f5711057fe11a4f4121504486
deleted: sha256:e71ced47e80a7fccfea1710f1e5a257d4e16fc3e96b05616007e15829e71a7b2
deleted: sha256:55bed58453479c2accfc08fabc929aece7d324af0df94335dd46333db9da1d23
deleted: sha256:ef96fdd4473a7ca9d39a50e0feae50131de083cee4f11060ad8bee1bc853b2b5Total reclaimed space: 0 B
[root@maven hellojib]# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED              SIZE
bolingcavalry/hellojib   0.0.1-SNAPSHOT      3afd4165b6b6        About a minute ago   505 MB

小结四:提升构建速度

在使用命令mvn compile jib:dockerBuild构建本地镜像时,每次构建的过程中都会提示以下信息:

[INFO] Containerizing application to Docker daemon as bolingcavalry/hellojib:0.0.1-SNAPSHOT...
[INFO] The base image requires auth. Trying again for openjdk:8-jdk-stretch...
[INFO] Executing tasks:
[INFO] [=========                     ] 30.0% complete
[INFO] > pulling base image manifest

每次构建都会显示上面的内容,也就是说每次都去远程拉取base镜像的manifest(pulling base image manifest),这部分时间导致整体构架时间变长,以下是构建结果,可见用了10秒:

[INFO] Built image to Docker daemon as bolingcavalry/hellojib:0.0.1-SNAPSHOT
[INFO] Executing tasks:
[INFO] [==============================] 100.0% complete
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.722 s
[INFO] Finished at: 2019-09-01T08:55:09+08:00
[INFO] ------------------------------------------------------------------------

首先想到的是执行命令docker pull openjdk:8-jdk-stretch将base镜像下载到本地仓库,再尝试构建,遗憾的是jib依旧会远程获取base镜像的manifest,还是很慢;

如果能避免远程拉取base镜像的manifest,镜像构建速度应该会快一些;基于此推论,优化构建速度的步骤如下:

  1. 在本机创建registry(docker镜像仓库服务);
  2. 将base镜像openjdk:8-jdk-stretch放入本机registry;
  3. 修改pom.xml中base镜像的配置,改为本机registry的镜像;
  4. 如此一来,每次都会从本机registry取得base镜像的manifest,不走远程请求响应,构建时间会有提升;

接下按照上述步骤进行操作:

  1. 确认当前电脑的IP地址,我这里是192.168.121.131;
  2. 设置本地docker服务支持http:修改docker配置文件:/etc/docker/daemon.json,在json中增加内容"insecure-registries": [“192.168.121.131:5000”]
  3. 重启docker使配置生效:
systemctl restart docker
  1. 在本地创建一个镜像仓库服务:
docker run --name docker-registry -d -p 5000:5000 registry
  1. 查看本地镜像openjdk:8-jdk-stretch的ID为08ded5f856cc;
  2. 用tag命令将本地镜像openjdk:8-jdk-stretch改名,命令如下所示,"192.168.121.131"是当前电脑的IP地址:
docker tag 08ded5f856cc 192.168.121.131:5000/openjdk:8-jdk-stretch
  1. 再次查看镜像,发现多了个192.168.121.131:5000/openjdk:8u212-jdk-stretch:
[root@maven hellojib]# docker tag 08ded5f856cc 192.168.121.131:5000/openjdk:8-jdk-stretch
[root@maven hellojib]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
bolingcavalry/hellojib         0.0.1-SNAPSHOT      6601ef5a767d        3 minutes ago       505 MB
192.168.121.131:5000/openjdk   8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MB
docker.io/openjdk              8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MB
  1. 将192.168.121.131:5000/openjdk:8-jdk-stretch推送到远程仓库,命令如下所示,由于镜像名前缀是192.168.121.131:5000,镜像会被推送到我们刚刚创建的registry:
docker push 192.168.121.131:5000/openjdk:8-jdk-stretch
  1. 修改java工程的pom.xml,将base镜像由之前的openjdk:8-jdk-stretch改为192.168.121.131:5000/openjdk:8-jdk-stretch
  2. 修改java工程的pom.xml,增加allowInsecureRegistries,使jib插件支持http协议连接镜像仓库(安全起见,默认是关闭的),整个插件的配置信息如下:
<plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--使用jib插件--><plugin><groupId>com.google.cloud.tools</groupId><artifactId>jib-maven-plugin</artifactId><version>1.3.0</version><configuration><!--from节点用来设置镜像的基础镜像,相当于Docerkfile中的FROM关键字--><from><!--使用openjdk官方镜像,tag是8-jdk-stretch,表示镜像的操作系统是debian9,装好了jdk8--><image>192.168.121.131:5000/openjdk:8-jdk-stretch</image></from><to><!--镜像名称和tag,使用了mvn内置变量${project.version},表示当前工程的version--><image>bolingcavalry/hellojib:${project.version}</image></to><!--容器相关的属性--><container><!--jvm内存参数--><jvmFlags><jvmFlag>-Xms4g</jvmFlag><jvmFlag>-Xmx4g</jvmFlag></jvmFlags><!--要暴露的端口--><ports><port>8080</port></ports><useCurrentTimestamp>true</useCurrentTimestamp></container><allowInsecureRegistries>true</allowInsecureRegistries></configuration></plugin></plugins>
  1. 再次执行命令mvn compile jib:dockerBuild,如下所示,时间从之前的10秒缩减到3.9秒:
[INFO] Built image to Docker daemon as bolingcavalry/hellojib:0.0.1-SNAPSHOT
[INFO] Executing tasks:
[INFO] [==============================] 100.0% complete
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.949 s
[INFO] Finished at: 2019-09-01T10:51:50+08:00
[INFO] ------------------------------------------------------------------------

以上就是通过registry服务提升jib构建速度的方法,在多人开发的时候,registry可以配置为一个公共的,多人都可使用,毕竟pom.xml代码存在公共代码仓库,每个人都去修改成自己的registry的地址是不合适的,一旦提交上去会影响其他人的使用,我们这里的做法是将registry的地址写成host,本地维护好host和IP的映射就可以了。
使用本地registry服务,除了提速,在服务器无法连接中央仓库取得openjdk:8-jdk-stretch的manifest时,这种方式能保证构建依旧能够成功;

小结五:将jib与mvn构建的生命周期绑定

  1. 前面的实战中构建命令是mvn compile jib:dockerBuild,实际上可以做到仅用mvn compile就完成镜像构建,这是maven插件的通用特性;
  2. 修改pom.xml增加executions节点,里面设置compile触发jib:dockerBuild,整个插件的内容如下所示:
<plugin><groupId>com.google.cloud.tools</groupId><artifactId>jib-maven-plugin</artifactId><version>1.3.0</version><configuration><!--from节点用来设置镜像的基础镜像,相当于Docerkfile中的FROM关键字--><from><!--使用openjdk官方镜像,tag是8-jdk-stretch,表示镜像的操作系统是debian9,装好了jdk8--><image>192.168.121.131:5000/openjdk:8-jdk-stretch</image></from><to><!--镜像名称和tag,使用了mvn内置变量${project.version},表示当前工程的version--><image>bolingcavalry/hellojib:${project.version}</image></to><!--容器相关的属性--><container><!--jvm内存参数--><jvmFlags><jvmFlag>-Xms4g</jvmFlag><jvmFlag>-Xmx4g</jvmFlag></jvmFlags><!--要暴露的端口--><ports><port>8080</port></ports><useCurrentTimestamp>true</useCurrentTimestamp></container><allowInsecureRegistries>true</allowInsecureRegistries></configuration><executions><execution><phase>compile</phase><goals><goal>dockerBuild</goal></goals></execution></executions></plugin>
  1. 执行命令mvn compile -DskipTests,如下所示,可以成功构建镜像,与前面的命令结果一致:
[root@maven hellojib]# mvn compile -DskipTests
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< com.bolingcavalry:hellojib >---------------------
[INFO] Building hellojib 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ hellojib ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ hellojib ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- jib-maven-plugin:1.3.0:dockerBuild (default) @ hellojib ---
[WARNING] Setting image creation time to current time; your image may not be reproducible.
[INFO]
[INFO] Containerizing application to Docker daemon as bolingcavalry/hellojib:0.0.1-SNAPSHOT...
[INFO]
[INFO] Container entrypoint set to [java, -Xms4g, -Xmx4g, -cp, /app/resources:/app/classes:/app/libs/*, com.bolingcavalry.hellojib.HellojibApplication]
[INFO]
[INFO] Built image to Docker daemon as bolingcavalry/hellojib:0.0.1-SNAPSHOT
[INFO] Executing tasks:
[INFO] [==============================] 100.0% complete
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.721 s
[INFO] Finished at: 2019-09-01T11:43:23+08:00
[INFO] ------------------------------------------------------------------------
[root@maven hellojib]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
bolingcavalry/hellojib         0.0.1-SNAPSHOT      5e3f62d13a73        35 seconds ago      505 MB
192.168.121.131:5000/openjdk   8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MB
docker.io/openjdk              8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MB
docker.io/registry             latest              f32a97de94e1        5 months ago        25.8 MB

小结六:父子结构的maven工程如何构建

  1. 假设当前maven工程是父子结构的,有两个子工程A和B,其中A是二方库,提供一个jar包,里面是接口类和Bean类,B是springboot应用,并且B的源码中用到了A提供的接口和Bean;
  2. 上述父子结构的maven工程是常见的工程结构,此时如果要将B构建成Docker镜像,在B的目录下执行mvn compile jib:dockerBuild显然是不行的,因为没有编译构建A,会导致B的编译失败;
  3. 此时最好的做法就是将jib与mvn构建的生命周期绑定,修改B的pom.xml文件,加入executions节点;
  4. 在父工程目录下执行mvn compile,此时maven会先编译构建整个工程,然后再将B工程的构建结果制作成镜像;

以上就是我在近期使用Jib插件时遇到的问题小结,希望这些小技巧可以给您提供一些参考,助您解决问题;

欢迎关注我的公众号:程序员欣宸

Jib使用小结(Maven插件版)相关推荐

  1. Intellij IDEA社区版集成Maven插件

    Intellij IDEA社区版集成Maven插件 第一步: 打开Intellij IDEA , Preference -> Plugins , 搜索 Maven Intergration和Ma ...

  2. IntelliJ IDEA中Maven插件无法更新索引之解决办法

    为什么80%的码农都做不了架构师?>>>    Maven的仓库.索引 中央仓库:目前来说,http://repo1.maven.org/maven2/ 是真正的Maven中央仓库的 ...

  3. Maven实战——常用Maven插件介绍

    http://www.infoq.com/cn/news/2011/04/xxb-maven-7-plugin 我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任 ...

  4. eclipse maven插件创建java web项目(2)

    为什么80%的码农都做不了架构师?>>>    好了.马不停蹄,再来一篇使用骨架创建maven web项目的方法,大神就不要看了,小白快来学习吧 开始, 1>创建maven项目 ...

  5. 构建maven项目插件_如何构建一个Maven插件

    构建maven项目插件 使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证,管理和保护. 今天尝试Okta. 由于其插件生态系统的普 ...

  6. 如何构建一个Maven插件

    使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证,管理和保护. 今天尝试Okta. 由于其插件生态系统的普及,Apache Mav ...

  7. 常用Maven插件介绍(下)(转)

    我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...

  8. fest556_FEST JavaFX编译器Maven插件

    fest556 FEST的JavaFX编译器Maven插件已达到1.0b1版. 该插件编译JavaFX源文件和测试文件. 它不需要将JavaFX分发存储在Maven存储库中,也不需要将所有JavaFX ...

  9. 前端资源压缩合并maven插件之wro4j

    前端资源压缩合并maven插件之wro4j 原文写于 2014-05-14 https://github.com/kuitos/kuitos.github.io/issues/5 参考文章:前端性能优 ...

  10. 核心之外的8个必备Maven插件

    使用Maven作为构建管理工具,您已经习惯了其核心插件和功能. 现在, 是时候启动您的Maven游戏并发现可以为您最喜欢的构建工具添加省时功能的顶级插件了 . 如果您是Java开发人员,则可能熟悉Ma ...

最新文章

  1. 简单介绍nginx 变量使用
  2. 微型计算机工业控制技术,基于ARM的微机原理与接口技术(STM32嵌入式系统架构编程与应用嵌入式与工业控制技术高等学校电子信息类专业系列教材)...
  3. 李宁-2015年7月13日-个人文档
  4. Java多对多关系示例
  5. layui中table显示 图片
  6. (转载)SQL基础-- 约束(CONSTRAINT)
  7. STL两种格式:文本格式与二进制格式
  8. 关于Eclipse安装插件出现An error occurred while collecting items to be installed解决办法
  9. 为什么央行降息降准,会导致债券价格上涨?
  10. Tomcat配置指定JDK
  11. 【愚公系列】2022年07月 Go教学课程 004-Go代码注释
  12. fpga 中的slew rate 什么意思
  13. 异贝,通过移动互联网技术,为中小微实体企业联盟、线上链接、线上线下自定义营销方案推送。案例60
  14. OkHttp优点及工作原理
  15. PCB设计入门—学习记录
  16. 从普通 Msconfig 启动选择转为选择性启动
  17. spydroid_ipcamera源码分析-图解,android ip摄像头
  18. 黑客盗号:窃取他人信息,行骗利器
  19. 关于长途托运物流的选择
  20. 【动画展示】Focusky教程 | 添加logo

热门文章

  1. tds for mysql_PostgreSQL9.3安装tds_fdw扩展
  2. paip 破解网站手机验证码
  3. SonarQube扫描的Bug、漏洞以及异味的修复(持续更新)
  4. 单片机外围模块漫谈之四,USB总线基本概念
  5. 写给三维建模入门小白的建议
  6. 【论文】解读A time-dependent shared autonomous vehicle system design problem
  7. java异步队对联_对联广告(带关闭的)
  8. 【U8】凭证上修改使用自定义项科目的辅助信息
  9. 【面试题】为什么需要 public static void main (String[ ] args) 这个方法?
  10. 路由器开启WDS模式扩展WIFI覆盖范围