You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gradle Shadow Plugin打包Jar在Docker容器运行报错:无主清单属性

问题分析与解决方案

你的问题核心出在Docker镜像构建时复制了错误的Jar文件,或者Dockerfile中Jar文件名不匹配,导致容器内运行的Jar并非你本地测试的Shadow Fat Jar。

可能的原因

  1. Gradle同时生成了普通Jar和Shadow Fat Jar
    默认情况下,Gradle的jar任务会生成一个不含依赖的普通Jar,而shadowJar任务生成Fat Jar,两者共存于build/libs目录。当你用COPY build/libs/*jar fat_jar_name-all.jar时,Docker可能会复制到普通Jar(按文件名排序后被选中),而普通Jar的MANIFEST可能缺失主类属性。

  2. Dockerfile中文件名逻辑冲突
    你将复制的Jar重命名为fat_jar_name-all.jar,但ENTRYPOINT中执行的是java -jar fat_jar_name.jar——虽然你的错误信息指向fat_jar_name-all.jar,但说明实际复制到容器的Jar并非你本地测试的Shadow Fat Jar。

解决方案

1. 固定Shadow Jar的文件名(Gradle配置)

修改shadowJar任务,指定固定的输出文件名,避免版本号干扰,同时可禁用普通Jar任务减少混淆:

tasks {
    "build" {
        dependsOn(shadowJar)
    }
    // 禁用普通jar任务,避免生成多余Jar
    jar {
        enabled = false
    }
    shadowJar {
        mergeServiceFiles {
            var path = "META-INF/"
        }
        manifest.inheritFrom(jar.get().manifest)
        manifest.attributes["Main-Class"] = "some.main.class.Main"
        manifest.attributes["Implementation-Version"] = version
        // 固定输出文件名
        archiveFileName = "fat_jar_name-all.jar"
    }
}

2. 修正Dockerfile,明确复制Shadow Jar

修改Dockerfile,指定精确的Jar文件名,避免模糊匹配导致的错误:

FROM eclipse-temurin:17
# 明确指定Shadow生成的Jar
ARG JAR_FILE=build/libs/fat_jar_name-all.jar
COPY ${JAR_FILE} app.jar
# 使用数组形式的ENTRYPOINT(更规范,避免命令解析问题)
ENTRYPOINT ["java", "-jar", "/app.jar"]

3. 构建前清理旧产物

构建Docker镜像前,先执行Gradle清理命令,确保build/libs目录只有最新的Shadow Jar:

gradle clean build

4. 验证容器内的Jar(可选)

如果仍有问题,可进入容器验证Jar内容:

# 启动交互容器
docker run -it --rm image_name bash
# 查看Jar内的MANIFEST文件
unzip -p app.jar META-INF/MANIFEST.MF

确认输出包含正确的Main-Class属性。

内容的提问来源于stack exchange,提问作者buzoherbert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:35:20