services: zookeeper: image: confluentinc/cp-zookeeper:7.4.0 environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka:7.4.0 depends_on: [zookeeper] ports: - "9092:9092" environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 spark: image: bitnami/spark:3.5 depends_on: [kafka] environment: SPARK_MODE: master spark-worker: image: bitnami/spark:3.5 depends_on: [spark] environment: SPARK_MODE: worker SPARK_MASTER_URL: spark://spark:7077
services: zookeeper: image: confluentinc/cp-zookeeper:7.4.0 environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka:7.4.0 depends_on: [zookeeper] ports: - "9092:9092" environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 spark: image: bitnami/spark:3.5 depends_on: [kafka] environment: SPARK_MODE: master spark-worker: image: bitnami/spark:3.5 depends_on: [spark] environment: SPARK_MODE: worker SPARK_MASTER_URL: spark://spark:7077
services: zookeeper: image: confluentinc/cp-zookeeper:7.4.0 environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka:7.4.0 depends_on: [zookeeper] ports: - "9092:9092" environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 spark: image: bitnami/spark:3.5 depends_on: [kafka] environment: SPARK_MODE: master spark-worker: image: bitnami/spark:3.5 depends_on: [spark] environment: SPARK_MODE: worker SPARK_MASTER_URL: spark://spark:7077
Error response from daemon: failed to resolve reference
"docker.io/bitnami/spark:3.5": not found
Error response from daemon: failed to resolve reference
"docker.io/bitnami/spark:3.5": not found
Error response from daemon: failed to resolve reference
"docker.io/bitnami/spark:3.5": not found
spark: image: apache/spark:3.5.1-python3 environment: SPARK_MODE: master
spark: image: apache/spark:3.5.1-python3 environment: SPARK_MODE: master
spark: image: apache/spark:3.5.1-python3 environment: SPARK_MODE: master
spark: image: apache/spark:3.5.1-python3 command: /opt/spark/sbin/start-master.sh
spark: image: apache/spark:3.5.1-python3 command: /opt/spark/sbin/start-master.sh
spark: image: apache/spark:3.5.1-python3 command: /opt/spark/sbin/start-master.sh
PID 1 is running → container is running
PID 1 exits → container exits immediately
PID 1 is running → container is running
PID 1 exits → container exits immediately
PID 1 is running → container is running
PID 1 exits → container exits immediately
#!/bin/bash
nohup java -cp $SPARK_CLASSPATH org.apache.spark.deploy.master.Master &
echo "Master started."
exit 0
#!/bin/bash
nohup java -cp $SPARK_CLASSPATH org.apache.spark.deploy.master.Master &
echo "Master started."
exit 0
#!/bin/bash
nohup java -cp $SPARK_CLASSPATH org.apache.spark.deploy.master.Master &
echo "Master started."
exit 0
t=0.0s Container starts; PID 1 = start-master.sh (bash)
t=0.1s Bash forks a Java process (Spark Master) into the background
t=0.2s Bash script reaches exit 0 → PID 1 terminates
t=0.2s Docker detects PID 1 exit → tears down the container
t=0.2s The background Java process is killed along with it
t=0.0s Container starts; PID 1 = start-master.sh (bash)
t=0.1s Bash forks a Java process (Spark Master) into the background
t=0.2s Bash script reaches exit 0 → PID 1 terminates
t=0.2s Docker detects PID 1 exit → tears down the container
t=0.2s The background Java process is killed along with it
t=0.0s Container starts; PID 1 = start-master.sh (bash)
t=0.1s Bash forks a Java process (Spark Master) into the background
t=0.2s Bash script reaches exit 0 → PID 1 terminates
t=0.2s Docker detects PID 1 exit → tears down the container
t=0.2s The background Java process is killed along with it
exec kafka-server-start /etc/kafka/server.properties
exec kafka-server-start /etc/kafka/server.properties
exec kafka-server-start /etc/kafka/server.properties
spark: image: apache/spark:3.5.1-python3 command: ["tail", "-f", "/dev/null"] volumes: - ./spark-apps:/opt/spark-apps
spark: image: apache/spark:3.5.1-python3 command: ["tail", "-f", "/dev/null"] volumes: - ./spark-apps:/opt/spark-apps
spark: image: apache/spark:3.5.1-python3 command: ["tail", "-f", "/dev/null"] volumes: - ./spark-apps:/opt/spark-apps
docker exec my-spark-container \ /opt/spark/bin/spark-submit \ /opt/spark-apps/my_job.py
docker exec my-spark-container \ /opt/spark/bin/spark-submit \ /opt/spark-apps/my_job.py
docker exec my-spark-container \ /opt/spark/bin/spark-submit \ /opt/spark-apps/my_job.py
command: > bash -c " /opt/spark/bin/spark-class org.apache.spark.deploy.master.Master --host spark --port 7077 --webui-port 8080 "
command: > bash -c " /opt/spark/bin/spark-class org.apache.spark.deploy.master.Master --host spark --port 7077 --webui-port 8080 "
command: > bash -c " /opt/spark/bin/spark-class org.apache.spark.deploy.master.Master --host spark --port 7077 --webui-port 8080 "
#!/bin/bash
# custom-entrypoint.sh
/opt/spark/sbin/start-master.sh # starts daemon in background
tail -f /opt/spark/logs/* # blocks + streams logs to stdout
#!/bin/bash
# custom-entrypoint.sh
/opt/spark/sbin/start-master.sh # starts daemon in background
tail -f /opt/spark/logs/* # blocks + streams logs to stdout
#!/bin/bash
# custom-entrypoint.sh
/opt/spark/sbin/start-master.sh # starts daemon in background
tail -f /opt/spark/logs/* # blocks + streams logs to stdout
volumes: - ./custom-entrypoint.sh:/opt/custom-entrypoint.sh
command: bash /opt/custom-entrypoint.sh
volumes: - ./custom-entrypoint.sh:/opt/custom-entrypoint.sh
command: bash /opt/custom-entrypoint.sh
volumes: - ./custom-entrypoint.sh:/opt/custom-entrypoint.sh
command: bash /opt/custom-entrypoint.sh - Docker containers exit when PID 1 exits. Always.
- start-master.sh backgrounds Spark with & and exits — which kills the container.
- Confluent's images use exec, making the service itself PID 1 and keeping the container alive.
- The fix: ensure PID 1 is a foreground process that never returns. - command & — background execution, PID 1 exits shortly after → container dies
- exec command — replaces PID 1, container lives as long as the process does → container survives
- nohup command & — classic daemon pattern, same problem as & in Docker → container dies