GitLab CI加载Docker镜像后报错:找不到或无法加载主类sh
问题原因
你的自定义镜像设置了ENTRYPOINT ["/usr/bin/java"],而GitLab CI执行step_script时,会默认向容器传递sh -c <CI脚本内容>作为命令参数。因为ENTRYPOINT被设为Java,容器会把sh当作Java主类名去加载——但sh是系统的shell二进制文件,根本不是Java类,所以会抛出Error: Could not find or load main class sh的错误。
你测试的RUN java -classpath /bin/sh sh命令也会报错,逻辑完全一致:你让Java去加载名为sh的类,但/bin/sh是可执行文件,不是Java类路径下的类文件,Java自然找不到对应的主类。
解决方案
以下是几种可行的解决方式,按需选择:
1. 修改自定义镜像的Dockerfile
调整镜像的ENTRYPOINT,让GitLab CI能正常启动shell执行脚本:
- 移除ENTRYPOINT:直接删除Dockerfile里的
ENTRYPOINT ["/usr/bin/java"]行,镜像会继承基础镜像maven:3.6.0-jdk-8的默认ENTRYPOINT(shell类型),可正常处理GitLab CI的命令。 - 改为shell类型ENTRYPOINT:如果必须保留ENTRYPOINT配置,改成shell入口:
ENTRYPOINT ["/bin/sh", "-c"]
2. 在GitLab CI Job中覆盖ENTRYPOINT
不想修改镜像的话,在.gitlab-ci.yml的对应Job里添加entrypoint: [""],清空镜像的ENTRYPOINT,让GitLab CI的默认命令sh -c ...直接作为容器CMD执行:
your_job_name: image: gitlab-my_repo/maven3-jdk-8-git:V0.1 entrypoint: [""] script: - # 你的CI脚本内容
3. 保留Java作为ENTRYPOINT(特殊场景)
如果镜像原本是用来直接运行Java程序的,只是临时在CI里执行脚本,可以在CI脚本里显式启动shell:
your_job_name: image: gitlab-my_repo/maven3-jdk-8-git:V0.1 script: - /bin/sh -c "你的CI脚本内容"
这种方式需要把所有脚本内容放在引号内,不如前两种方案便捷。
内容的提问来源于stack exchange,提问作者Martinxxntfxx
相关产品推荐
相关产品推荐

