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

Docker部署Spring Boot应用遇NoClassDefFoundError问题求助

问题描述

尝试通过docker-compose搭配Dockerfile构建并运行基于apka:apka镜像的Spring Boot容器,但容器无法启动,抛出如下异常:

21:42 Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
at ZadanieRekrutacyjne.ZadanieRekrutacyjne.ZadanieRekrutacyjneApplication.main(ZadanieRekrutacyjneApplication.java:16)
 Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
 1 more

曾尝试调整Spring Boot版本解决依赖兼容问题,但无效,还手动在资源目录添加了MANIFEST-INF目录及MANIFEST.FM文件。以下是相关配置与代码:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>ZadanieRekrutacyjne</groupId>
    <artifactId>ZadanieRekrutacyjne</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ZadanieRekrutacyjne</name>
    <description>Plants</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>3.0.4</version>        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>3.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.0.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <version>3.0.4</version>
        </dependency>
    </dependencies>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>4.0.1.RELEASE</version>
                    <executions>
                        <execution>
                            <configuration>
                                <excludes>
                                    <exclude>
                                        <groupId>org.projectlombok</groupId>
                                        <artifactId>lombok</artifactId>
                                    </exclude>
                                </excludes>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

Dockerfile

FROM openjdk:17
ADD target/ZadanieRekrutacyjne-0.0.1-SNAPSHOT.jar ZadanieRekrutacyjne-0.0.1-SNAPSHOT.jar
CMD ["java", "-jar", "/ZadanieRekrutacyjne-0.0.1-SNAPSHOT.jar"]

docker-compose.yml

version: '3.8'

services:
  sql-test:
    container_name: sql-test
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: zadanierekrutacyjne
      MYSQL_USER: recruit
      MYSQL_PASSWORD: recruit
      MYSQL_ROOT_PASSWORD: Krzysiek123qweasd,./
    volumes:
      - "./sql-test:/data/mysqldb"
    expose:
      - "3306"
    ports:
      - "3307:3306"
    restart: always


  apka:
    container_name: apka
    image: apka:apka
    build: .
    ports:
      - "8080:8080"
    environment:
      - spring.profiles.active=
    depends_on:
      - sql-test

主类代码

package ZadanieRekrutacyjne.ZadanieRekrutacyjne;

import ZadanieRekrutacyjne.ZadanieRekrutacyjne.Security.Security;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EntityScan("ZadanieRekrutacyjne.ZadanieRekrutacyjne.Entity")
@EnableJpaRepositories("ZadanieRekrutacyjne.ZadanieRekrutacyjne.Repositories")
@Import(Security.class)
public class ZadanieRekrutacyjneApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZadanieRekrutacyjneApplication.class, args);
    }
}

MANIFEST.FM

Manifest-Version: 1.0
Build-Jdk: 17.0.5
Main-Class: ZadanieRekrutacyjne.ZadanieRekrutacyjne.ZadanieRekrutacyjneApplication

application.properties

spring.jpa.hibernate.ddl-auto=update
#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/zadanierekrutacyjne
spring.datasource.url=jdbc:mysql://host.docker.internal:3307/zadanierekrutacyjne?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username=recruit
spring.datasource.password=recruit
#spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect

主类路径:ZadanieRekrutacyjne.ZadanieRekrutacyjne.ZadanieRekrutacyjneApplication


问题分析与解决方案

这个NoClassDefFoundError核心原因是打包后的jar包缺少Spring Boot核心依赖,具体问题出在以下几个方面:

1. Spring Boot版本严重不兼容

  • 父pom用的是2.6.2,但手动指定的starter依赖(如web、thymeleaf、test)用的是3.0.4,Spring Boot 3.x要求Java 17,而你的pom指定的是Java 11,版本完全不匹配,导致依赖冲突,打包时无法正确引入核心类。
  • 同时spring-boot-maven-plugin用的是4.0.1.RELEASE,这也是Spring Boot 3.x的插件版本,和2.6.2的父pom完全不兼容。

解决:统一Spring Boot版本
要么全用2.x,要么升级到3.x并对应Java版本:

  • 方案一(保留Java 11):把所有手动指定版本的starter依赖去掉version,让父pom的2.6.2管理版本;同时把spring-boot-maven-plugin版本改为2.6.2,并移出pluginManagement(因为pluginManagement只是声明,不会实际执行打包)。
    修改后的pom.xml关键部分:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/>
    </parent>
    <!-- 所有starter依赖去掉手动指定的version -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <!-- ...其他同理 -->
    <build>
        <!-- 移除pluginManagement,直接配置插件 -->
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.6.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal> <!-- 必须添加这个goal才会生成可执行jar -->
                        </goals>
                        <configuration>
                            <excludes>
                                <exclude>
                                    <groupId>org.projectlombok</groupId>
                                    <artifactId>lombok</artifactId>
                                </exclude>
                            </excludes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
  • 方案二(升级到Spring Boot 3.x):把父pom版本改为3.0.4,Java版本改为17,插件版本保持3.0.4(注意Spring Boot 3.x的插件版本没有RELEASE后缀),同时mysql-connector-java要改为mysql-connector-j(3.x不再支持旧的artifactId)。

2. Maven打包配置错误

  • spring-boot-maven-plugin放在了pluginManagement里,这只会声明插件,不会实际执行打包逻辑,导致生成的jar是普通jar,不是Spring Boot的可执行jar(没有包含所有依赖)。
  • 缺少repackage goal,这是Spring Boot插件生成可执行jar的关键步骤。

解决:将插件移出pluginManagement,添加repackage goal
如上面方案一中的修改,确保插件直接在build/plugins下,且包含repackage目标。

3. 手动添加MANIFEST.FM是多余操作

Spring Boot的maven插件会自动生成正确的MANIFEST文件,手动添加的文件会被插件覆盖,反而可能导致混乱,直接删除资源目录下的MANIFEST-INF目录即可。

4. 额外注意:Docker镜像Java版本匹配

如果用方案一(Java 11),Dockerfile要改为FROM openjdk:11,而不是17;如果用方案二(Java 17),则保持openjdk:17。

最后验证步骤

  1. 执行mvn clean package,确保打包成功,生成的jar在target目录下。
  2. 本地先运行java -jar target/ZadanieRekrutacyjne-0.0.1-SNAPSHOT.jar,确认能正常启动,排除Docker之外的问题。
  3. 再执行docker-compose up --build重新构建并运行容器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:27:01