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

Docker部署Maven Spark应用报SparkSession类找不到异常排查

问题根因

抛出java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession的核心原因是你打进Docker镜像的Jar包未包含Spark等第三方依赖,和Docker环境本身无关,本地直接执行java -jar target/my.script.spark.jar也会出现完全相同的错误。本地IDE运行无异常是因为Eclipse会自动把Maven依赖加入运行类路径,和打包出的Jar内容无关。
具体配置错误有3个:

  • 所有Maven插件配置都放在<pluginManagement>标签下,该标签仅用于锁定插件版本、给子模块提供继承配置,当前项目不会实际执行这部分插件逻辑,你配置的打包规则完全没生效
  • 重复定义了两次maven-jar-plugin,且jar-with-dependencies(包含依赖的胖包)是maven-assembly-plugin的配置项,maven-jar-plugin本身不支持把依赖打入Jar包,配置配错了插件
  • 生成的默认Jar包仅包含你自己写的业务代码,所有第三方依赖都在本地Maven仓库里,没有被打包进Jar,容器里没有本地Maven仓库的依赖,自然找不到类。
修复步骤

1. 修正pom.xml的打包配置

删除原<build>块内的全部内容,替换为如下配置,移除无效的<pluginManagement>标签,改用正确的maven-assembly-plugin打包含所有依赖的胖包:

<build>
    <finalName>my.script.spark</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <appendAssemblyId>false</appendAssemblyId>
                <archive>
                    <manifest>
                        <mainClass>my.script.spark.App</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-full-jar</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

注意:如果后续你需要把Jar提交到独立Spark集群运行,可以把Spark相关依赖的scope设置为provided,集群会自带Spark依赖不需要打入包内;但你当前是直接通过java -jar在容器内启动,必须保持Spark依赖为默认的compile scope,否则依赖不会被打入胖包。

2. 重新打包验证

在项目根目录执行mvn clean package,或者在Eclipse中右键项目 -> Run As -> Maven Build,Goals输入clean package执行打包。
打包完成后检查target目录下的my.script.spark.jar,大小应该在200M以上,本地先执行java -jar target/my.script.spark.jar验证,确认本地能正常启动不报错,再进行镜像构建。

3. 重新构建镜像启动服务

你的Dockerfile和docker-compose.yml配置没有问题,直接重新构建镜像即可:

docker build -t user/my_spark .

构建完成后执行docker-compose up启动容器,就不会再报类找不到的错误,不需要在镜像内单独安装Spark。

可选优化
  • 你当前pom中引入的hadoop-hdfs 2.2.0版本和Spark 2.4.0内置的Hadoop 2.7.x版本不兼容,后续运行大概率会出现HDFS相关报错,建议直接删除该依赖,Spark自带的Hadoop依赖足够支撑常规运行;如果必须指定Hadoop版本,需要和Spark编译使用的Hadoop版本保持一致。
  • 如果不想打几百兆的胖包,可以通过maven-dependency-plugin把依赖拷贝到单独目录,在Dockerfile中把依赖目录复制进镜像,启动时通过-cp参数指定类路径,但打胖包是配置最少、出错概率最低的方式,适合简单Spark脚本场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 01:39:18