Gradle Docker构建问题:单独复制JAR失败 主类com.library.api.MainKt无法加载
问题1:仅复制JAR文件的路径修正
你遇到的路径错误是因为官方gradle:6.9.1-jdk17镜像的默认工作目录为/home/gradle,你执行COPY指令时的所有文件都是放到该目录下,而非/home根目录。
你之前的COPY --from=builder /home/* /home指令实际是将/home下的gradle目录整体复制到了目标镜像的/home路径下,所以才会生成/home/build/libs/api.jar的目录结构。
如果要单独复制JAR文件,直接使用如下指令即可:
COPY --from=builder /home/gradle/build/libs/api.jar ./
配合ENTRYPOINT修改为ENTRYPOINT [ "java", "-jar", "./api.jar" ]即可正常运行。
问题2:主类找不到的根因与解决方案
核心问题是编译和运行的JDK版本不兼容:
- builder阶段使用JDK17编译,且build.gradle.kts中明确指定Kotlin编译的jvmTarget为15,生成的字节码版本为JDK15对应的59.0
- 运行阶段使用的
openjdk:8-jre-slim仅支持最高52.0版本的字节码(对应JDK8),无法识别高版本字节码的类文件,因此抛出找不到主类的错误。
你本地构建的JAR可以正常运行,是因为你本地测试时要么运行环境的JRE版本≥15,要么本地Gradle运行的JDK版本较低,实际编译生成的字节码版本符合JDK8的要求。
解决方案
二选一即可:
- 统一使用高版本运行环境:将第二阶段的基础镜像替换为
openjdk:17-jre-slim,保留现有编译配置即可。 - 必须使用JDK8运行的情况:
- 修改build.gradle.kts中的jvmTarget为
"1.8" - 将builder阶段的基础镜像替换为
gradle:6.9.1-jdk8,保证编译和运行的JDK版本完全匹配。
- 修改build.gradle.kts中的jvmTarget为
验证方式
可以在builder阶段的构建指令后追加验证逻辑,确认编译产物正常:
RUN gradle build --no-daemon \ && jar tf build/libs/api.jar | grep "com/library/api/MainKt.class" \ && unzip -p build/libs/api.jar META-INF/MANIFEST.MF | grep "Main-Class"
如果输出包含对应类和正确的主类配置,即说明编译产物无问题。
内容的提问来源于stack exchange,提问作者chunkydigits
相关产品推荐
相关产品推荐

