Docker容器运行Java应用报NoClassDefFoundError 已引入JSON依赖仍报错
问题解决方法
问题根因
默认执行mvn clean package生成的jar包仅包含项目自身编译后的类文件,不会将pom.xml中引入的第三方依赖包打包进去。你本地IDE运行时会自动把所有依赖加载到类路径下,所以运行正常,但直接执行java -jar命令时就会缺失依赖类,和Docker运行环境无关,你本地直接运行target目录下的jar包也会抛出完全相同的错误。
修复步骤
1. 配置Maven插件打包全量依赖(Fat Jar)
推荐使用maven-assembly-plugin插件实现所有依赖打入同一jar包,在你的pom.xml的<build><plugins>节点下添加如下配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <!-- 这里替换成你实际的主类全路径,无包名则直接写Main_lager --> <mainClass>Main_lager</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
2. 修改Dockerfile对应jar包名称
添加上述插件后,执行mvn package会在target目录生成两个jar包:
- 原jar:
vs-lager-1.0-SNAPSHOT.jar(仅含自身代码) - 全量依赖jar:
vs-lager-1.0-SNAPSHOT-jar-with-dependencies.jar(可直接运行)
所以需要修改Dockerfile中COPY和CMD对应的jar包名称,同时建议对齐构建和运行阶段的JDK版本,避免兼容性问题:
FROM maven:3.6.3-jdk-8 AS BUILD COPY pom.xml /tmp/ COPY src /tmp/src/ WORKDIR /tmp/ RUN mvn clean package FROM openjdk:8 COPY --from=BUILD /tmp/target/vs-lager-1.0-SNAPSHOT-jar-with-dependencies.jar /tmp/vs-lager.jar CMD ["java", "-jar", "/tmp/vs-lager.jar"]
3. 可选方案
如果有依赖包冲突等特殊场景,也可以选择maven-shade-plugin实现全量依赖打包,功能更灵活,支持对依赖包进行重命名等定制操作。
验证方法
配置完成后可以先在本地执行mvn clean package,然后直接运行java -jar target/vs-lager-1.0-SNAPSHOT-jar-with-dependencies.jar,确认本地运行正常后再构建Docker镜像即可。
内容的提问来源于stack exchange,提问作者Egen30
相关产品推荐
相关产品推荐

