未记录事实核验 · 状态:维护中
记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。
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 关联阅读
三、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)。
下一步
- 继续阅读:Docker网络与存储 - 理解容器间通信和数据持久化
- 实战进阶:Docker实战场景 - ETL 容器化和数据服务部署