Spark Docker 单机部署全攻略:从环境搭建到任务运行

一、为什么选择Spark Docker单机部署?

Apache Spark作为分布式计算框架,传统部署需配置Hadoop集群、ZooKeeper等组件,过程复杂且资源占用高。Docker容器化技术通过轻量级虚拟化,将Spark运行环境封装为独立镜像,实现”开箱即用”的单机部署方案。其核心优势包括:

  1. 环境一致性:消除不同操作系统间的配置差异,确保开发、测试、生产环境高度一致。
  2. 资源隔离:通过CPU/内存限制避免任务间资源争抢,特别适合多版本Spark共存场景。
  3. 快速迭代:镜像版本管理支持回滚,配合CI/CD流程可实现自动化部署。
  4. 学习成本低:无需深入掌握YARN/Mesos等集群管理器,专注Spark核心功能开发。

典型应用场景包括算法原型验证、学生实验环境、临时数据分析任务等。某金融科技公司通过Docker部署Spark,将POC环境搭建时间从3天缩短至2小时,验证了该方案的实用性。

二、Docker环境准备

2.1 基础环境要求

  • 操作系统:Linux(推荐Ubuntu 20.04+)/macOS(Docker Desktop)/Windows 10(WSL2)
  • 资源配置:建议4核CPU、8GB内存、50GB磁盘空间
  • 软件依赖:Docker Engine(版本≥20.10)、curl、wget

验证环境命令:

  1. docker --version
  2. # 应输出类似:Docker version 24.0.5, build 2ed8007
  3. free -h # 查看可用内存
  4. df -h # 查看磁盘空间

2.2 网络配置优化

为避免端口冲突,需规划Spark Web UI(默认8080)、历史服务器(18080)等端口映射。建议修改/etc/docker/daemon.json(Linux)或Docker Desktop设置(macOS/Windows),启用固定IP池:

  1. {
  2. "default-address-pools": [
  3. {"base": "172.28.0.0/16", "size": 24}
  4. ]
  5. }

重启Docker服务后,通过docker network inspect bridge验证配置。

三、Spark Docker镜像选择与定制

3.1 官方镜像分析

Apache官方提供两类镜像:

  • 基础镜像bitnami/spark:3.5.0(含OpenJDK 11)
  • 完整镜像bitnami/spark:3.5.0-debian-11-r0(包含Python/R支持)

通过docker pull命令获取镜像:

  1. docker pull bitnami/spark:3.5.0
  2. docker images | grep spark # 验证镜像

3.2 自定义镜像构建

当需要特定配置时,可通过Dockerfile定制镜像。示例配置Spark历史服务器:

  1. FROM bitnami/spark:3.5.0
  2. COPY spark-defaults.conf /opt/bitnami/spark/conf/
  3. RUN echo "spark.eventLog.enabled true" >> /opt/bitnami/spark/conf/spark-defaults.conf \
  4. && echo "spark.eventLog.dir file:///tmp/spark-events" >> /opt/bitnami/spark/conf/spark-defaults.conf \
  5. && mkdir /tmp/spark-events

构建并运行:

  1. docker build -t my-spark:3.5.0 .
  2. docker run -d -p 8080:8080 -v /tmp/spark-events:/tmp/spark-events my-spark:3.5.0

四、单机部署核心配置

4.1 启动参数详解

关键启动参数需通过SPARK_DAEMON_JAVA_OPTS环境变量设置:

  1. docker run -d \
  2. --name spark-master \
  3. -p 8080:8080 -p 7077:7077 \
  4. -e SPARK_MODE=master \
  5. bitnami/spark:3.5.0
  • -p 8080:8080:映射Web UI端口
  • -p 7077:7077:集群管理器端口
  • SPARK_MODE=master:指定为Master节点

4.2 启动Worker节点

在单机模拟集群时,可启动多个Worker:

  1. docker run -d \
  2. --name spark-worker-1 \
  3. -p 8081:8081 \
  4. -e SPARK_MODE=worker \
  5. -e SPARK_MASTER_URL=spark://host.docker.internal:7077 \
  6. -e SPARK_WORKER_MEMORY=2g \
  7. bitnami/spark:3.5.0
  • SPARK_MASTER_URL:需指向宿主机IP(macOS/Windows)或host.docker.internal
  • SPARK_WORKER_MEMORY:限制Worker内存使用

4.3 配置文件优化

修改spark-defaults.conf实现持久化配置:

  1. spark.master spark://host.docker.internal:7077
  2. spark.driver.memory 4g
  3. spark.executor.memory 2g
  4. spark.serializer org.apache.spark.serializer.KryoSerializer

通过-v参数挂载配置文件:

  1. docker run -d \
  2. --name spark-custom \
  3. -v $(pwd)/conf:/opt/bitnami/spark/conf \
  4. bitnami/spark:3.5.0

五、任务提交与监控

5.1 交互式Shell使用

启动Spark Shell进行即时数据分析:

  1. docker run -it --rm \
  2. -e SPARK_MASTER_URL=spark://host.docker.internal:7077 \
  3. bitnami/spark:3.5.0 spark-shell

示例计算π值:

  1. scala> val slices = 100
  2. scala> val n = math.min(100000L * slices, Int.MaxValue).toInt
  3. scala> val count = sc.parallelize(1 to n, slices).map { i =>
  4. val x = Math.random() * 2 - 1
  5. val y = Math.random() * 2 - 1
  6. if (x*x + y*y < 1) 1 else 0
  7. }.reduce(_ + _)
  8. scala> println("Pi is roughly " + 4.0 * count / n)

5.2 批量任务提交

提交PySpark作业示例:

  1. docker run -it --rm \
  2. -v $(pwd)/scripts:/scripts \
  3. -e SPARK_MASTER_URL=spark://host.docker.internal:7077 \
  4. bitnami/spark:3.5.0 \
  5. spark-submit --class org.apache.spark.examples.SparkPi \
  6. /opt/bitnami/spark/examples/jars/spark-examples_2.12-3.5.0.jar 1000

5.3 监控与日志

访问http://localhost:8080查看Web UI,关键指标包括:

  • Alive Workers:可用Worker节点数
  • Memory Usage:已用/总内存
  • CPU Cores:可用核心数

日志收集建议:

  1. docker logs spark-master > spark-master.log 2>&1

六、高级场景实践

6.1 多版本共存

通过不同端口映射实现多版本Spark运行:

  1. # 启动Spark 3.3.0
  2. docker run -d -p 8082:8080 --name spark-3.3.0 bitnami/spark:3.3.0
  3. # 启动Spark 3.5.0
  4. docker run -d -p 8083:8080 --name spark-3.5.0 bitnami/spark:3.5.0

6.2 与Jupyter集成

创建包含Jupyter的Spark环境:

  1. FROM bitnami/spark:3.5.0
  2. RUN pip install jupyterlab pyspark
  3. CMD jupyter lab --ip=0.0.0.0 --port=8888 --allow-root --NotebookApp.token=''

运行后通过http://localhost:8888访问Notebook。

6.3 持久化存储

挂载宿主机目录实现数据持久化:

  1. docker run -d \
  2. --name spark-with-data \
  3. -v /data/spark:/data \
  4. -v /tmp/spark-events:/tmp/spark-events \
  5. bitnami/spark:3.5.0

七、常见问题与解决方案

7.1 端口冲突处理

当出现Bind for 0.0.0.0:8080 failed错误时:

  1. 使用docker ps查找冲突容器
  2. 停止冲突容器:docker stop <container_id>
  3. 或修改当前容器端口映射

7.2 内存不足优化

错误Container killed due to memory usage的解决方案:

  1. 调整Worker内存:-e SPARK_WORKER_MEMORY=1g
  2. 限制Driver内存:--conf spark.driver.memory=512m
  3. 增加Docker内存限制(Docker Desktop设置中)

7.3 网络连接问题

Mac/Windows用户需确保使用host.docker.internal而非localhost。验证方法:

  1. ping host.docker.internal # 应返回宿主机IP

八、最佳实践建议

  1. 资源预留:为系统保留至少2GB内存,避免宿主机卡死
  2. 镜像标签:使用具体版本标签(如3.5.0)而非latest
  3. 日志轮转:配置log4j.properties实现日志文件分割
  4. 安全加固:生产环境应禁用Web UI的--conf spark.ui.view.acls=*
  5. 性能调优:根据任务类型调整spark.sql.shuffle.partitions(默认200)

通过Docker部署Spark单机环境,开发者可在10分钟内完成从环境搭建到任务运行的全流程。某电商公司采用此方案后,数据分析团队的开发效率提升40%,硬件成本降低65%。建议结合CI/CD流程,将Spark镜像构建纳入自动化流水线,实现真正的”一键部署”。