Jib构建镜像问题从定位到深入分析

简介: 使用Jib插件构建的SpringBoot工程的镜像,在运行时报错:Could not find or load main class ${start-class},今天就来一起分析这个问题,除了解决它,还要追溯Jib作者的思路和行动,去深入了解

欢迎访问我的GitHub

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

问题简述

  • 通过Jib插件将SpringBoot工程制作成Docker镜像成功,但是运行镜像的时候报错(Could not find or load main class ${start-class}),今天来一起分析这个问题,希望能帮读者跳过小坑。

关于Jib插件

  • 在Maven工程中可以使用Jib插件将当前Java工程构建成Docker镜像,详情请参考:
  1. 《Docker与Jib(maven插件版)实战》;
  2. 《Jib使用小结(Maven插件版)》;

环境信息

  1. 操作系统:macOS Mojave 10.14.6 (18G103)
  2. JDK:10.14.6 (18G103)
  3. Docker:10.14.6 (18G103)
  4. SpringBoot:2.1.8.RELEASE
  5. Jib插件版本:1.6.1

源码下载

  • 为了重现问题,我将出现问题的SpringBoot工程上传到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项目中有多个文件夹,本章的应用在jib-error-demo文件夹下,如下图红框所示:

在这里插入图片描述

问题:

  • 在pom.xml文件所在目录执行命令mvn clean compile -U,镜像可以构建成功,但是控制台输出了警告信息,如下图:

在这里插入图片描述

  • 尝试用此镜像创建容器,行命令docker run --name=test bolingcavalry/hellojib:0.0.1-SNAPSHOT,报错如下:
CN0014005932:~ zhaoqin$ docker run --name=test bolingcavalry/hellojib:0.0.1-SNAPSHOT
Error: Could not find or load main class ${start-class}
  • docker ps -a查看容器信息如下,只能看到状态是"退出",别的没啥了:
CN0014005932:~ zhaoqin$ docker ps -a
CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS                     PORTS               NAMES
d618f6588821        bolingcavalry/hellojib:0.0.1-SNAPSHOT   "java -Xms4g -Xmx4g …"   4 minutes ago       Exited (1) 4 minutes ago                       test
  • 不甘心,用命令docker ps -a --no-trunc查看未截断的容器信息:
CN0014005932:~ zhaoqin$ docker ps -a --no-trunc
CONTAINER ID                                                       IMAGE                                   COMMAND                                                                           CREATED             STATUS                     PORTS               NAMES
d618f6588821f00d3bd0b67a85ff92988b90dfff710370c9d340d5c544c550af   bolingcavalry/hellojib:0.0.1-SNAPSHOT   "java -Xms4g -Xmx4g -cp /app/resources:/app/classes:/app/libs/* ${start-class}"   7 minutes ago       Exited (1) 7 minutes ago                       test
  • 这次有新发现,容器启动时执行命令是java -Xms4g -Xmx4g -cp /app/resources:/app/classes:/app/libs/* ${start-class}</font>,怪哉!这个<font color="red">\${start-class}是什么?我们来看一个正常镜像的启动命令:
java -Xms4g -Xmx4g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.jiberrordemo.JibErrorDemoApplication
  • 如上所示,com.bolingcavalry.jiberrordemo.JibErrorDemoApplication是main方法所在类,此命令可以正常运行JibErrorDemoApplication类的main方法;
  • 小结问题:容器启动时执行java命令,把&dollar;{start-class}作为参数传给java,导致java无法处理此参数,所以进程报错,导致容器退出;

问题原因

  • 此问题的原因很简单:java工程中带有main方法的类不止一个,去查看jib-error-demo工程的代码,发现Utils.java中果然有个main方法:
public class Utils {

    public static String time(){
      return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()).toString();
    }

    public static void main(String[] args){
        System.out.println(time());
    }
}
  • 将上述main方法删除掉,再构建镜像并运行容器,证实问题已经解决。

另一种解决问题的方法

  • 如果不想动Utils类的代码(也许jar包中某个类带有main方法),请打开pom.xml文件,在jib插件的配置中增加mainClass节点,节点内容是指定的class类,如下图红框所示:

在这里插入图片描述

  • 经过上面的设置,问题也可以解决。
  • 接下来,如果您有兴趣了解更深层次的原因,咱们一起来深度探险吧。

查找问题

  • 这个问题在Jib的官方GitHub上是有记录的,先看第一条,地址是:https://github.com/GoogleContainerTools/jib/issues/1601 ,如下图红框所示,同样的问题,最后issue的发起人自己关闭了这个issue,因为他发现这自己的项目中有两个带有main方法的类:

在这里插入图片描述

  • 再来看看这个issue, https://github.com/GoogleContainerTools/jib/issues/170 ,Jib的作者Q Chen推测是Spring将&dollar;{start-class}这个字符串设置为Main-Class属性的值(个人感觉,这里说的Spring应该是spring boot的mave插件吧),于是Jib插件在使用Main-Class的值得时候,拿到的就是&dollar;{start-class}这个字符串了:

在这里插入图片描述

  • 170这个issue的后续情节很有意思,Jib作者Q Chen对这个问题也很纠结,如果Java工程中发现了多个带有main方法的类,Jib究竟该如何处理呢?Q Chen最后决定输出警告,如下图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 此时的您,如果依然意犹未尽,咱们再来巩固一下SpringBoot的start-class

关于start-class

  • 熟悉SpringBoot的同学其实对&dollar;{start-class}并不陌生,当工程中多个类中都有main方法时,使用该参数来指定SpringBoot的启动类;
  • 先看SpringBoot官方文档熟悉一下start-class,地址是:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ ,下图内容比较关键:我们设置的启动类被指定到Start-Class属性中,而Main-Class属性变成了org.springframework.boot.loader.JarLauncher,这才是SpringBoot真正的启动类:

在这里插入图片描述

  • 如下图,这是个补充说明,Main-Class属性的值被转移到Start-Class属性这个动作,是maven插件在构建jar的时候做的:

在这里插入图片描述

  • 所以start-class的值是来自main-class,再看main-class的值从哪里来,如下图红框所示,maven插件会去查找带有public static void main(String[] args)的类:

在这里插入图片描述

  • 至此,Jib构建的镜像问题分析完毕,一个小小的问题引发了这么多学习和探索,虽然有点费时间,但是可以让人再次感受到"技术是相通的"感觉,不知道您有没有这种感觉呢?

欢迎关注阿里云开发者社区博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...
相关文章
|
Kubernetes 安全 Linux
开源Chart包安全分析发布,阿里云视角容器安全基线的重要性
云原生环境下,容器成为了软件开发过程中打包与分发的标准。
312 0
开源Chart包安全分析发布,阿里云视角容器安全基线的重要性
|
4月前
|
Prometheus 监控 Cloud Native
【揭秘可观测性】构建完美参考框架,打造系统监控的瑞士军刀!
【8月更文挑战第25天】在现代软件设计中,可观测性是确保系统稳定性和效率的关键因素。它主要由日志、指标及链路追踪(统称LMx)三大核心组件构成。本文详细介绍了构建高效可观测性框架的六个步骤:需求分析、工具选择、数据收集策略设计、实施集成、数据可视化及持续优化。并通过一个Spring Boot应用集成Prometheus和Micrometer收集指标的示例,展示了具体实践方法。合理构建可观测性框架能显著提升团队对软件系统的管理和监控能力,进而增强系统整体性能和可靠性。
80 2
|
5月前
|
Java
性能优化思路及常用工具及手段问题之stack工具分析异常数据问题如何解决
性能优化思路及常用工具及手段问题之stack工具分析异常数据问题如何解决
|
7月前
|
人工智能 大数据 5G
400G光模块已经部署,需求将进一步扩大
2023年底,电信运营商完成400G OTN试验网设备部署,标志着400G技术大规模部署的开端。400G传输技术日趋成熟,预计2024年实现长距离商用。400G光模块在提升数据传输效率、降低能耗方面发挥关键作用,适应云计算、大数据、AI对高效算力的需求。光纤技术行业显现复苏态势,400G光模块部署成为数据中心发展的必然,支持新兴技术发展。随着5G、云计算等技术进步,对高速光模块需求激增,推动光纤行业创新与市场扩张。
76 2
|
人工智能 运维 监控
在日常开发工作中,日志数据该如何利用?
在日常开发工作中,日志数据是一个宝贵的资源,它可以提供关于应用程序运行状态、错误报告、性能指标和用户行为等方面的重要信息。正确地利用和分析日志数据可以帮助开发人员更好地理解应用程序的运行情况,快速定位和解决问题,改进应用程序的性能,并为业务决策提供有力支持。尤其是在现代科技发展的背景下,日志数据作为一种重要的信息资源,对于运维工作具有极大的价值。然而,如何充分利用日志数据,并将其应用于运维和开发工作中,仍然是许多企业和运维和开发人员关注的问题。那么本文就来分享一下在日常开发中关于日志数据的利用方面的探讨。
312 1
在日常开发工作中,日志数据该如何利用?
|
存储 人工智能 运维
日常工作中,你对于日志数据都是如何利用的?
近期阿里云宣布日志服务 SLS 内核迎来全新升级(https://developer.aliyun.com/topic/sls_pay_by_ingested_data1?spm=a2c6h.13066369.question.3.7f77533dUZ1xiM),通过运维领域模型加持,全链路提升智能分析能力,以更稳定、更智能、更高效、更普惠的平台全方面帮助企业加速拥抱云原生和AI;目前我公司日志服务的使用场景,以及公司自研的日志系统。
118 1
|
物联网 Go 开发者
《Docker多阶段构建:优化镜像构建过程,高效部署应用的利器》
《Docker多阶段构建:优化镜像构建过程,高效部署应用的利器》
174 0
|
算法 数据安全/隐私保护 计算机视觉
超实用开发加速工具收集,分享给你吧~(一)
超实用开发加速工具收集,分享给你吧~
超实用开发加速工具收集,分享给你吧~(一)
|
Web App开发 监控 Kubernetes
日志调试不理想?试试分布式追踪优势
日志调试不理想?试试分布式追踪优势
212 0
日志调试不理想?试试分布式追踪优势