未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用范围与待维护事项

本文用于隔离的本地开发实验,需具备 Compose、容器网络和数据卷基础,不是生产部署方案。固定口令、明文 Kafka 和未限制地址的端口映射不可直接用于公网或共享环境。镜像标签、环境变量及资源数值尚未实测核验;Kafka 的 localhost 广播地址不适用于容器客户端,Hadoop 首次格式化和持久化目录待验证。不同方案可能有端口及容器名冲突,作业文件和 HDFS 测试文件需自行准备。

Docker 数据开发环境搭建

abstract 本章要点

  • MySQL / PostgreSQL 本地开发数据库
  • Redis 缓存服务
  • Kafka 消息队列
  • Spark 单机模式(含 PySpark)
  • Flink 单机模式
  • Hadoop 伪分布式
  • Jupyter Notebook 数据分析环境
  • 一个完整的数据开发栈 Compose 文件

note 本章使用方式

每个服务都提供了独立的启动命令和 Compose 配置。你可以单独启动某个服务,也可以把需要的服务组合到一个 Compose 文件里统一管理。


一、MySQL

单独启动

# MySQL 8.0(推荐版本)
docker run -d \
  --name mysql \
  --restart unless-stopped \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=dev_db \
  -p 3306:3306 \
  -v ~/docker-data/mysql:/var/lib/mysql \
  mysql:8.0 \
  --character-set-server=utf8mb4 \
  --collation-server=utf8mb4_unicode_ci

# 验证启动
docker exec mysql mysql -uroot -proot123 -e "SELECT VERSION();"

# 连接信息
# Host: 127.0.0.1 | Port: 3306 | User: root | Password: root123

Compose 配置

# docker-compose.yml 片段
services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: dev_db
      MYSQL_USER: dev
      MYSQL_PASSWORD: dev123
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init-sql:/docker-entrypoint-initdb.d   # 放 .sql 文件自动初始化
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --max_connections=200
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot123"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

volumes:
  mysql-data:

tip 关联阅读

更多 MySQL 使用和优化,参见 MySQL学习路线图


二、PostgreSQL

# PostgreSQL 16
docker run -d \
  --name postgres \
  --restart unless-stopped \
  -e POSTGRES_USER=admin \
  -e POSTGRES_PASSWORD=admin123 \
  -e POSTGRES_DB=dev_db \
  -p 5432:5432 \
  -v ~/docker-data/postgres:/var/lib/postgresql/data \
  postgres:16

# 连接验证
docker exec -it postgres psql -U admin -d dev_db -c "SELECT version();"

# 连接信息
# Host: 127.0.0.1 | Port: 5432 | User: admin | Password: admin123

tip 关联阅读

参见 PostgreSQL学习路线图


三、Redis

# Redis 7(带密码、数据持久化)
docker run -d \
  --name redis \
  --restart unless-stopped \
  -p 6379:6379 \
  -v ~/docker-data/redis:/data \
  redis:7-alpine \
  redis-server --requirepass redis123 --appendonly yes

# 验证
docker exec redis redis-cli -a redis123 ping
# 输出:PONG

# 查看 Redis 信息
docker exec redis redis-cli -a redis123 INFO server

四、Kafka

Kafka 是数据工程中常见的消息队列,本地测试最麻烦的一个,Docker 让这件事变得简单很多。

note Kafka 版本说明

KRaft 在 Kafka 3.3 之前已提供,Kafka 3.3 起达到生产就绪状态,可不依赖 ZooKeeper。以下提供两种本地实验方式:带 ZooKeeper 的传统模式和 KRaft 单节点模式;是否适用需结合 Kafka 版本及部署需求判断。

方式一:KRaft 模式(不需要 ZooKeeper,推荐新手)

# 使用 Bitnami Kafka(内置 KRaft 支持)
docker run -d \
  --name kafka \
  --restart unless-stopped \
  -p 9092:9092 \
  -e KAFKA_CFG_NODE_ID=0 \
  -e KAFKA_CFG_PROCESS_ROLES=controller,broker \
  -e KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093 \
  -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 \
  -e KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT \
  -e KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093 \
  -e KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER \
  -v ~/docker-data/kafka:/bitnami/kafka \
  bitnami/kafka:3.7

# 验证 Kafka 启动
docker exec kafka kafka-topics.sh --list --bootstrap-server localhost:9092

# 创建测试 Topic
docker exec kafka kafka-topics.sh \
  --create \
  --topic test-topic \
  --bootstrap-server localhost:9092 \
  --partitions 3 \
  --replication-factor 1

# 发送消息
docker exec -it kafka kafka-console-producer.sh \
  --topic test-topic \
  --bootstrap-server localhost:9092

# 消费消息(新终端)
docker exec -it kafka kafka-console-consumer.sh \
  --topic test-topic \
  --from-beginning \
  --bootstrap-server localhost:9092

方式二:带 ZooKeeper 的完整环境(含 Kafka UI)

# docker-compose-kafka.yml
services:

  zookeeper:
    image: bitnami/zookeeper:3.9
    container_name: zookeeper
    restart: unless-stopped
    ports:
      - "2181:2181"
    environment:
      ALLOW_ANONYMOUS_LOGIN: "yes"
    volumes:
      - zk-data:/bitnami/zookeeper

  kafka:
    image: bitnami/kafka:3.7
    container_name: kafka
    restart: unless-stopped
    ports:
      - "9092:9092"
    environment:
      KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_CFG_LISTENERS: PLAINTEXT://:9092
      KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      ALLOW_PLAINTEXT_LISTENER: "yes"
      KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true"
    volumes:
      - kafka-data:/bitnami/kafka
    depends_on:
      - zookeeper

  # Kafka Web UI - 可视化管理
  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: kafka-ui
    restart: unless-stopped
    ports:
      - "8081:8080"
    environment:
      KAFKA_CLUSTERS_0_NAME: local-kafka
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
      KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
    depends_on:
      - kafka

volumes:
  zk-data:
  kafka-data:
# 启动
docker compose -f docker-compose-kafka.yml up -d

# 访问 Kafka UI:http://localhost:8081

tip 关联阅读

参见 Kafka学习路线图 了解更多 Kafka 使用


五、Apache Spark(单机模式)

# docker-compose-spark.yml
services:

  # Spark Master 节点
  spark-master:
    image: bitnami/spark:3.5
    container_name: spark-master
    environment:
      SPARK_MODE: master
      SPARK_RPC_AUTHENTICATION_ENABLED: "no"
      SPARK_RPC_ENCRYPTION_ENABLED: "no"
      SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED: "no"
      SPARK_SSL_ENABLED: "no"
    ports:
      - "8080:8080"   # Spark Master Web UI
      - "7077:7077"   # Spark Master 通信端口
    volumes:
      - ./spark-jobs:/opt/bitnami/spark/jobs
    deploy:
      resources:
        limits:
          memory: 2G

  # Spark Worker 节点(此配置固定容器名和宿主机端口;启动多个前需调整命名与端口映射)
  spark-worker:
    image: bitnami/spark:3.5
    container_name: spark-worker-1
    environment:
      SPARK_MODE: worker
      SPARK_MASTER_URL: spark://spark-master:7077
      SPARK_WORKER_MEMORY: 2G
      SPARK_WORKER_CORES: 2
      SPARK_RPC_AUTHENTICATION_ENABLED: "no"
      SPARK_RPC_ENCRYPTION_ENABLED: "no"
    ports:
      - "8081:8081"   # Worker Web UI
    depends_on:
      - spark-master
    deploy:
      resources:
        limits:
          memory: 2G
# 启动 Spark 集群
docker compose -f docker-compose-spark.yml up -d

# 访问 Spark Master UI:http://localhost:8080

# 提交 PySpark 任务
docker exec spark-master spark-submit \
  --master spark://spark-master:7077 \
  /opt/bitnami/spark/jobs/my_job.py

# 启动 PySpark 交互式 Shell
docker exec -it spark-master pyspark \
  --master spark://spark-master:7077

tip 关联阅读

参见 Spark学习路线图 了解更多 Spark 使用


六、Apache Flink(单机模式)

# docker-compose-flink.yml
services:

  # Flink JobManager
  jobmanager:
    image: flink:1.19-scala_2.12
    container_name: flink-jobmanager
    ports:
      - "8082:8081"   # Flink Web UI
    command: jobmanager
    environment:
      FLINK_PROPERTIES: |
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 4
        parallelism.default: 2
    volumes:
      - flink-data:/opt/flink/data
      - ./flink-jobs:/opt/flink/jobs
    deploy:
      resources:
        limits:
          memory: 1G

  # Flink TaskManager
  taskmanager:
    image: flink:1.19-scala_2.12
    container_name: flink-taskmanager
    command: taskmanager
    environment:
      FLINK_PROPERTIES: |
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 4
        parallelism.default: 2
    depends_on:
      - jobmanager
    deploy:
      resources:
        limits:
          memory: 2G

volumes:
  flink-data:
# 启动 Flink
docker compose -f docker-compose-flink.yml up -d

# 访问 Flink Web UI:http://localhost:8082

# 提交 Flink 任务
docker exec flink-jobmanager \
  flink run /opt/flink/jobs/my_job.jar

# 查看运行中的 Job
docker exec flink-jobmanager flink list

tip 关联阅读

参见 Flink学习路线图 了解更多 Flink 使用


七、Jupyter Notebook / Lab

# 方式一:标准 Jupyter Lab(含 Python 数据科学包)
docker run -d \
  --name jupyter \
  --restart unless-stopped \
  -p 8888:8888 \
  -e JUPYTER_TOKEN=mytoken123 \
  -v $(pwd)/notebooks:/home/jovyan/work \
  -v $(pwd)/data:/home/jovyan/data \
  jupyter/datascience-notebook:latest

# 访问:http://localhost:8888/lab?token=mytoken123


# 方式二:PySpark Notebook(含 Spark)
docker run -d \
  --name jupyter-spark \
  --restart unless-stopped \
  -p 8888:8888 \
  -p 4040:4040 \
  -e JUPYTER_TOKEN=mytoken123 \
  -v $(pwd)/notebooks:/home/jovyan/work \
  --memory=6g \
  jupyter/pyspark-notebook:latest

# 访问:http://localhost:8888/lab?token=mytoken123
# Spark UI:http://localhost:4040(运行 Spark 任务后才会出现)

Jupyter 镜像选择指南

镜像 包含内容 大小 适合场景
jupyter/minimal-notebook 基础 Jupyter ~600MB 最小化,自行安装包
jupyter/scipy-notebook 科学计算包(numpy/scipy/matplotlib) ~1.5GB 数据分析
jupyter/datascience-notebook 数据科学全家桶(pandas/sklearn 等) ~2.5GB 日常数据分析推荐
jupyter/pyspark-notebook 含 PySpark ~3.5GB Spark 开发测试

八、Hadoop 伪分布式

warning Hadoop 资源需求较高

Hadoop 伪分布式模式需要至少 4GB 内存。如果只是学习 HDFS 基本操作,建议只启动必要组件。

# docker-compose-hadoop.yml
services:

  # NameNode(HDFS 主节点)
  namenode:
    image: apache/hadoop:3
    container_name: namenode
    hostname: namenode
    command: ["hdfs", "namenode"]
    ports:
      - "9870:9870"   # HDFS Web UI
      - "8020:8020"   # HDFS 服务端口
    environment:
      HADOOP_HOME: /opt/hadoop
      CLUSTER_NAME: test-cluster
    env_file:
      - ./hadoop.env
    volumes:
      - namenode-data:/hadoop/dfs/name
    deploy:
      resources:
        limits:
          memory: 1G

  # DataNode(HDFS 数据节点)
  datanode:
    image: apache/hadoop:3
    container_name: datanode
    command: ["hdfs", "datanode"]
    env_file:
      - ./hadoop.env
    volumes:
      - datanode-data:/hadoop/dfs/data
    depends_on:
      - namenode
    deploy:
      resources:
        limits:
          memory: 1G

  # YARN ResourceManager
  resourcemanager:
    image: apache/hadoop:3
    container_name: resourcemanager
    hostname: resourcemanager
    command: ["yarn", "resourcemanager"]
    ports:
      - "8088:8088"   # YARN Web UI
    env_file:
      - ./hadoop.env
    depends_on:
      - namenode

  # YARN NodeManager
  nodemanager:
    image: apache/hadoop:3
    container_name: nodemanager
    command: ["yarn", "nodemanager"]
    env_file:
      - ./hadoop.env
    depends_on:
      - resourcemanager

volumes:
  namenode-data:
  datanode-data:
# hadoop.env 配置文件
CORE-SITE.XML_fs.default.name=hdfs://namenode:8020
CORE-SITE.XML_fs.defaultFS=hdfs://namenode:8020
HDFS-SITE.XML_dfs.namenode.rpc-address=namenode:8020
HDFS-SITE.XML_dfs.replication=1
MAPRED-SITE.XML_mapreduce.framework.name=yarn
YARN-SITE.XML_yarn.resourcemanager.hostname=resourcemanager
# 启动 Hadoop
docker compose -f docker-compose-hadoop.yml up -d

# 查看 NameNode 启动日志(原稿约 30 秒为未核实估算;下方命令不执行格式化,也不能单独证明 HDFS 就绪,首次初始化需另行确认)
docker logs -f namenode | grep -m 1 "started"

# 访问 HDFS Web UI:http://localhost:9870
# 访问 YARN Web UI:http://localhost:8088

# HDFS 基本操作
docker exec namenode hdfs dfs -mkdir /data
docker exec namenode hdfs dfs -ls /
docker exec namenode hdfs dfs -put /tmp/test.txt /data/

tip 关联阅读

参见 Hadoop学习路线图 了解更多 Hadoop 使用


九、一键启动完整数据开发栈

把常用服务组合在一起,适合日常数据开发工作。

# docker-compose-data-stack.yml
# 完整数据开发环境:MySQL + PostgreSQL + Redis + Kafka + Jupyter
# 内存需求:至少 8GB

services:

  # ===== 关系型数据库 =====
  mysql:
    image: mysql:8.0
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: dev_db
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    networks:
      - data-net

  postgres:
    image: postgres:16
    container_name: postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: admin123
      POSTGRES_DB: dev_db
    ports:
      - "5432:5432"
    volumes:
      - pg-data:/var/lib/postgresql/data
    networks:
      - data-net

  # ===== 缓存 =====
  redis:
    image: redis:7-alpine
    container_name: redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    command: redis-server --requirepass redis123 --appendonly yes
    networks:
      - data-net

  # ===== 消息队列 =====
  zookeeper:
    image: bitnami/zookeeper:3.9
    container_name: zookeeper
    restart: unless-stopped
    environment:
      ALLOW_ANONYMOUS_LOGIN: "yes"
    volumes:
      - zk-data:/bitnami/zookeeper
    networks:
      - data-net

  kafka:
    image: bitnami/kafka:3.7
    container_name: kafka
    restart: unless-stopped
    ports:
      - "9092:9092"
    environment:
      KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_CFG_LISTENERS: PLAINTEXT://:9092
      KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      ALLOW_PLAINTEXT_LISTENER: "yes"
    volumes:
      - kafka-data:/bitnami/kafka
    depends_on:
      - zookeeper
    networks:
      - data-net

  # ===== 分析环境 =====
  jupyter:
    image: jupyter/pyspark-notebook:latest
    container_name: jupyter
    restart: unless-stopped
    ports:
      - "8888:8888"
      - "4040:4040"
    environment:
      JUPYTER_TOKEN: "mytoken123"
    volumes:
      - ./notebooks:/home/jovyan/work
      - ./data:/home/jovyan/data
    networks:
      - data-net
    deploy:
      resources:
        limits:
          memory: 4G

networks:
  data-net:
    driver: bridge

volumes:
  mysql-data:
  pg-data:
  redis-data:
  zk-data:
  kafka-data:
# 启动完整开发栈
docker compose -f docker-compose-data-stack.yml up -d

# 查看启动状态
docker compose -f docker-compose-data-stack.yml ps

# 访问地址:
# MySQL: 127.0.0.1:3306 (root/root123)
# PostgreSQL: 127.0.0.1:5432 (admin/admin123)
# Redis: 127.0.0.1:6379 (密码: redis123)
# Kafka: 127.0.0.1:9092
# Jupyter: http://localhost:8888 (token: mytoken123)

# 停止所有服务(保留数据)
docker compose -f docker-compose-data-stack.yml down

# 停止并删除本 Compose 声明的命名卷及附属匿名卷(不删除绑定挂载的宿主机文件;执行前确认备份)
docker compose -f docker-compose-data-stack.yml down -v

服务资源需求参考

以下数值为原稿未实测核验的本地实验估算,不是通用最低配置或容量保证;实际需求取决于镜像版本、数据量、并发、JVM 配置及 Docker 可用资源,应通过 docker stats 和作业运行结果确认。

服务 最低内存 推荐内存 说明
MySQL 512MB 1GB 测试环境够用
PostgreSQL 256MB 512MB 较轻量
Redis 128MB 256MB 非常轻量
ZooKeeper 512MB 512MB 相对稳定
Kafka 1GB 2GB 建议至少 1GB
Spark(1M+1W) 4GB 8GB 较重
Flink(1JM+1TM) 2GB 4GB 较重
Jupyter(PySpark) 4GB 6GB 取决于数据量
Hadoop(伪分布式) 4GB 8GB 最重


info 前置知识

  • Docker Compose入门 - 理解 Compose 的基本语法,本文是 Compose 的实战应用
  • 了解 Kafka、Spark 等组件的基本用途(会用就行,不需要深入原理)

掌握检查

  • [ ] 能用 Compose 在本地启动 MySQL + Redis,用客户端工具(如 DBeaver、Another Redis Desktop Manager)连接验证服务正常
  • [ ] 知道如何查看容器启动日志来确认服务是否真正就绪(MySQL 需要等待约 10-30 秒初始化)
  • [ ] 能合理分配 Docker 内存限制:Kafka + Spark 单机环境至少需要 6GB,知道如何通过 deploy.resources.limits.memory 配置
  • [ ] 了解数据卷持久化的重要性:MySQL 容器删除重建后,数据不能丢失
  • [ ] 能基于本文提供的 Compose 配置,增减服务(如去掉 Hadoop,只保留 MySQL + Kafka + Jupyter)

实践练习

基础题:启动 MySQL + Redis + Kafka(最小化配置),验证三个服务均正常运行:MySQL 能 SHOW DATABASES,Redis 能 PING 返回 PONG,Kafka 能创建 topic。记录三个服务各占用多少内存(docker stats)。


下一步