写点什么

Jib 使用小结 (Maven 插件版)

作者:程序员欣宸
  • 2022-10-14
    广东
  • 本文字数:7881 字

    阅读完需:约 26 分钟

Jib使用小结(Maven插件版)

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


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

关于 Jib 插件

全文概览

  • 本文由以下几部分组成:


  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 上下载本次实战的源码,地址和链接信息如下表所示:



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

小结一:三种构建参数

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


mvn compile jib:dockerBuild
复制代码


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


小结二:镜像的时间问题

  • 在使用命令 mvn compile jib:dockerBuild 构建本地镜像时,会遇到创建时间不准的问题:

  • 如下所示, bolingcavalry/hellojib 是刚刚使用 jib 插件构建的镜像,其生成时间(CREATED 字段)显示的是 49 years ago


[root@maven hellojib]# docker imagesREPOSITORY               TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/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 imagesREPOSITORY               TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/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 imagesREPOSITORY               TAG                 IMAGE ID            CREATED              SIZEbolingcavalry/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 pruneWARNING! This will remove all dangling images.Are you sure you want to continue? [y/N] yDeleted Images:deleted: sha256:7aa104e20b8a08bac3255f2627ac90f10021c6630370ce7a84ba33f89404b153deleted: sha256:7dd7376ae00c2df0411bac1eded4b3c79dd1528f5711057fe11a4f4121504486deleted: sha256:e71ced47e80a7fccfea1710f1e5a257d4e16fc3e96b05616007e15829e71a7b2deleted: sha256:55bed58453479c2accfc08fabc929aece7d324af0df94335dd46333db9da1d23deleted: sha256:ef96fdd4473a7ca9d39a50e0feae50131de083cee4f11060ad8bee1bc853b2b5
Total reclaimed space: 0 B[root@maven hellojib]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEbolingcavalry/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,不走远程请求响应,构建时间会有提升;


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

  • 确认当前电脑的 IP 地址,我这里是 192.168.121.131

  • 设置本地 docker 服务支持 http:修改 docker 配置文件:/etc/docker/daemon.json,在 json 中增加内容 "insecure-registries": ["192.168.121.131:5000"]

  • 重启 docker 使配置生效:


systemctl restart docker
复制代码


  • 在本地创建一个镜像仓库服务:


docker run --name docker-registry -d -p 5000:5000 registry
复制代码


  • 查看本地镜像 openjdk:8-jdk-stretch 的 ID 为 08ded5f856cc

  • 用 tag 命令将本地镜像 openjdk:8-jdk-stretch 改名,命令如下所示,"192.168.121.131"是当前电脑的 IP 地址:


docker tag 08ded5f856cc 192.168.121.131:5000/openjdk:8-jdk-stretch
复制代码


  • 再次查看镜像,发现多了个 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 imagesREPOSITORY                     TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/hellojib         0.0.1-SNAPSHOT      6601ef5a767d        3 minutes ago       505 MB192.168.121.131:5000/openjdk   8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MBdocker.io/openjdk              8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MB
复制代码


  • 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
复制代码


  • 修改 java 工程的 pom.xml,将 base 镜像由之前的 openjdk:8-jdk-stretch 改为 192.168.121.131:5000/openjdk:8-jdk-stretch

  • 修改 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>
复制代码


  • 再次执行命令 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 构建的生命周期绑定

  • 前面的实战中构建命令是 mvn compile jib:dockerBuild ,实际上可以做到仅用 mvn compile 就完成镜像构建,这是 maven 插件的通用特性;

  • 修改 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>
复制代码


  • 执行命令 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 imagesREPOSITORY                     TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/hellojib         0.0.1-SNAPSHOT      5e3f62d13a73        35 seconds ago      505 MB192.168.121.131:5000/openjdk   8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MBdocker.io/openjdk              8-jdk-stretch       08ded5f856cc        2 weeks ago         488 MBdocker.io/registry             latest              f32a97de94e1        5 months ago        25.8 MB
复制代码

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

  • 假设当前 maven 工程是父子结构的,有两个子工程 A 和 B,其中 A 是二方库,提供一个 jar 包,里面是接口类和 Bean 类,B 是 springboot 应用,并且 B 的源码中用到了 A 提供的接口和 Bean;

  • 上述父子结构的 maven 工程是常见的工程结构,此时如果要将 B 构建成 Docker 镜像,在 B 的目录下执行 mvn compile jib:dockerBuild 显然是不行的,因为没有编译构建 A,会导致 B 的编译失败;

  • 此时最好的做法就是将 jib 与 mvn 构建的生命周期绑定,修改 B 的 pom.xml 文件,加入 executions 节点;

  • 在父工程目录下执行 mvn compile ,此时 maven 会先编译构建整个工程,然后再将 B 工程的构建结果制作成镜像;

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

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...


发布于: 刚刚阅读数: 3
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018-04-19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
Jib使用小结(Maven插件版)_Docker_程序员欣宸_InfoQ写作社区