How to Run Apache Spark in Docker: A Complete Guide
Apache Spark has become the go-to engine for big‑data processing, and Docker gives you a lightweight, reproducible way to spin up Spark environments. This guide walks through everything you need—from picking a base image to orchestrating a multi‑node cluster and fine‑tuning performance. Whether you’re a data engineer or a developer testing a Spark job locally, you’ll find step‑by‑step instructions, best practices, and common pitfalls.
Why Docker Makes Apache Spark Development Easier
Running Spark on a bare machine can involve juggling Java versions, Hadoop binaries, and environment variables. Docker eliminates these headaches by packaging all dependencies into a single image. It guarantees that every developer, CI pipeline, and production deployment runs the same code in the same environment.
Setting Up Your Docker Environment
Before you start writing Dockerfiles, make sure you have Docker Engine installed. On Linux and macOS, you can install via the package manager; on Windows, Docker Desktop is the recommended choice. After installation, verify that you can run a hello‑world container with docker run hello-world.
Creating a Dockerfile for Spark
Choosing the Base Image
Apache Spark ships as a binary distribution, so you have a couple of options:
- Official Spark Image –
spark:3.5.2from Docker Hub includes Spark 3.x plus Java 17. - Custom Java Image – Start from
openjdk:17-jdk-slimand install Spark manually; useful if you need a specific Spark build or additional libraries.
The official image is the quickest path to a working cluster, but custom images let you layer your own JARs and configurations.
Installing Dependencies and Configuring Spark
Below is a sample Dockerfile that starts from the official Spark image, installs hadoop-client, and sets environment variables to point to a local Hive metastore. Adjust the ENV lines to match your own needs.
FROM spark:3.5.2# Optional: install Hadoop client for HDFS access
RUN apt-get update && apt-get install -y libhadoop2.10
ENV SPARK_HOME=/opt/spark
ENV PATH=$SPARK_HOME/bin:$PATH
# Copy custom Spark configs
COPY conf/ $SPARK_HOME/conf/
# Copy user JARs
COPY jars/ $SPARK_HOME/jars/
WORKDIR $SPARK_HOME
CMD ["spark-shell"]
Place any custom configuration files (e.g., spark-defaults.conf, hive-site.xml) inside a conf/ directory next to the Dockerfile. JARs can go into a jars/ folder.
Running Spark Clusters Inside Docker
Single Node (Standalone) Mode
The simplest way to test your Spark jobs is to run a single-node cluster:
docker build -t my-spark .docker run -d -p 7077:7077 -p 8080:8080 --name spark-master my-spark
After the container starts, the master UI is available at http://localhost:8080. You can submit jobs via the REST API or the spark-submit script inside the container.
Multi‑Node Cluster with Docker Compose
For production‑like setups, use Docker Compose to spin up a master and several workers. Here’s a minimal docker-compose.yml:
version: '3'services:
spark-master:
image: my-spark
container_name: spark-master
environment:
- SPARK_MODE=master
ports:
- 7077:7077
- 8080:8080
spark-worker-1:
image: my-spark
container_name: spark-worker-1
environment:
- SPARK_MODE=worker
- SPARK_MASTER_URL=spark://spark-master:7077
depends_on:
- spark-master
spark-worker-2:
image: my-spark
container_name: spark-worker-2
environment:
- SPARK_MODE=worker
- SPARK_MASTER_URL=spark://spark-master:7077
depends_on:
- spark-master
Start the cluster with docker compose up -d. The master UI now shows both workers, and you can scale workers by adding more services or using a deploy section with replicas.
Optimizing Spark Performance in Docker
Memory and CPU Limits
Docker’s resource limits help prevent a container from stealing host resources. Allocate at least 4 GB of RAM and 2 CPUs for a moderate cluster:
docker run -m 4g --cpus 2.0 -d my-sparkAdjust the spark.executor.memory and spark.driver.memory settings in conf/spark-defaults.conf to match the container limits.
Persisting Data with Volumes
To keep HDFS files or Spark checkpoint data between restarts, mount a volume:
docker run -v /host/data:/opt/spark/data -d my-sparkInside the container, point Spark’s spark.sql.warehouse.dir or spark.local.dir to /opt/spark/data. This approach also facilitates sharing data across multiple containers.
Common Pitfalls and Troubleshooting
- DNS Resolution – Workers may fail to resolve the master host if you use
localhostinSPARK_MASTER_URL. Use the service name defined in Docker Compose. - Port Conflicts – If port 7077 is already used, change the host mapping in the
docker runor Compose file. - Java Version Mismatch – Spark 3.5 requires Java 17. Ensure your base image matches this requirement.
- Volume Permission Issues – Docker may run containers as
root, leading to permission errors on mounted volumes. Add--user $(id -u):$(id -g)to align user IDs.
FAQ
- Can I run Spark inside a container that already has Hadoop? Yes, install Hadoop client packages or use a custom image that bundles Hadoop.
- Is Docker suitable for production Spark clusters? Docker works well for development and testing. For large‑scale production, consider Kubernetes or YARN for better scalability and resource isolation.
- How do I access the Spark UI from my host? Expose the master