Apache DolphinScheduler 单机部署实战 | Docker 一把梭,10分钟搞定!

📝 摘要:DolphinScheduler 单机模式(Standalone)Docker 部署实战:先对比单机、伪集群、集群三种模式的取舍,再手把手四步搭建——部署 MySQL 并用它替换默认 H2、初始化官方建表 SQL、挂载 MySQL 驱动、docker Compose 启动容器。

三个必踩的坑:容器内连宿主机数据库不能用 127.0.0.1、换 MySQL 后不会自动建表、不配 TZ 定时任务整整错开 8 小时。改用 MySQL 持久化后,可随时重建、零数据迁移、平滑升级到集群。适合中小团队离线数仓调度。你的离线数仓还在用 crontab 调度?每次任务挂了靠同事喊你才知道?是时候上一个正经的调度平台了。本文手把手带你用 Docker 单机模式部署 DolphinScheduler,10 分钟搞定,轻量够用,附赠监控方案。

DolphinScheduler 部署模式,选哪个?

DolphinScheduler 提供三种部署模式,先花 30 秒搞清楚区别,免得选错了回头重来(别问我怎么知道的 🥲):

模式 特点 适合场景
单机模式(Standalone) 所有服务跑在一个进程里,内置 ZooKeeper + H2 数据库,开箱即用 快速体验、测试环境、中小团队
伪集群模式(Pseudo-Cluster) 单台机器部署所有服务(Master、Worker、API Server 等),但各服务独立进程 需要更细粒度控制的单机场景
集群模式(Cluster) 多台机器部署,Master/Worker 可多节点水平扩展 大规模生产环境

一句话总结​:小团队用单机模式就够了——而且只要按本文的方式换掉默认数据库,将来升级集群是零数据迁移的(§六 会展开)。

二、为什么选单机模式?

网上铺天盖地的集群部署教程,看着就头大——3 台机器起步、ZooKeeper 集群、MySQL 主从……

打住! 你确定你的场景需要这么重?

以我的实际业务为例:

  • 🔢 ​25 个工作流​,每天产生不到 300 个工作流实例
  • 📊 每天任务实例不到 1500 个
  • ✅ 单机模式稳定运行,毫无压力

更关键的是——离线数仓场景下,即使 DolphinScheduler 短暂挂掉,​对线上业务零影响​。任务晚跑几分钟,数据不会丢,天不会塌。

💡 ​核心思路​:在单机模式基础上,​用 MySQL 替换默认的 H2 数据库​。注意 standalone 默认那个 H2 走的是 jdbc:h2:mem: ——​纯内存,不是「可能丢数据」,是容器一重启工作流定义、调度记录全部归零​。拿它跑生产,等于把家当放在断电就清空的柜子里。换成 MySQL,数据持久化才谈得上安心。

另一个好处是:数据存在 MySQL 后,DolphinScheduler 本身可以随时重建。后续如果需要集成插件、自定义镜像,直接重新部署容器,连上同一个 MySQL 即可恢复所有配置,零成本重来。

三、实战部署(四步搞定)

第一步:部署 MySQL

如果你已经有现成的 MySQL 实例,可以跳过这一步,直接建库授权即可。

docker run --name dolphin-mysql \  -e MYSQL_ROOT_PASSWORD='YourRootPass@2025' \  -e MYSQL_DATABASE=ds_scheduler \  -e MYSQL_USER=ds_admin \  -e MYSQL_PASSWORD='DsPass@2025' \  -p 13306:3306 \  -v /data/dolphin-mysql/data:/var/lib/mysql \  --restart unless-stopped \  -d mysql:8.0.42 \  --default-authentication-plugin=mysql_native_password \  --character-set-server=utf8mb4 \  --collation-server=utf8mb4_unicode_ci

几个注意点​:

  • 端口映射用了 13306 而非默认 3306,避免和宿主机已有的 MySQL 冲突
  • mysql_native_password 省掉 caching_sha2_password 在非 SSL 连接下要走 RSA 公钥交换的那一套麻烦。⚠️ ​注意版本​:这个参数在 MySQL 8.0.34 起已标记废弃(启动会打 deprecation 警告,但仍能用),​8.4 直接移除了该插件​——如果你用的是 8.4+,这行要删掉,改用 caching_sha2_password(8.x 的 JDBC 驱动本身是支持的)
  • 密码请务必修改为你自己的强密码​,别学我之前用 123456(真实故事,不展开说了)

第二步:初始化数据库表结构

MySQL 容器启动后只会创建一个空库,DolphinScheduler 需要的几十张表并不会自动生成。我们需要手动执行官方提供的初始化 SQL:

# 下载 DolphinScheduler 3.2.0 的 MySQL 初始化脚本wget -O /tmp/dolphinscheduler_mysql.sql \  https://raw.githubusercontent.com/apache/dolphinscheduler/3.2.0/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql# 将 SQL 文件拷贝到 MySQL 容器内docker cp /tmp/dolphinscheduler_mysql.sql dolphin-mysql:/tmp/# 执行初始化(注意替换为你自己的密码)docker exec -i dolphin-mysql mysql -uds_admin -p'DsPass@2025' ds_scheduler < /tmp/dolphinscheduler_mysql.sql

执行完后可以验证一下表是否创建成功:

docker exec dolphin-mysql mysql -uds_admin -p'DsPass@2025' ds_scheduler -e "SHOW TABLES;" | head -20

正常情况下应该能看到 t_ds_process_definitiont_ds_worker_group 等一系列表。如果输出为空,检查上一步 SQL 执行有没有报错。

这一步别跳过! 换成 MySQL 之后​没有任何自动建表​——H2 模式下开箱即用的那套初始化不会发生。跳过的后果就是启动后喜提 Table 'xxx' doesn't exist

第三步:下载 MySQL 驱动

DolphinScheduler 的 Docker 镜像默认不带 MySQL 驱动(毕竟人家也不知道你用哪个数据库),需要手动下载并挂载进容器:

mkdir -p /data/dolphin/lib/wget -P /data/dolphin/lib/ \  https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.30/mysql-connector-java-8.0.30.jar

🤔 为什么不用最新版驱动?一是 8.0.30 经过验证是兼容的,版本这东西——​能跑的不要动​,这是运维第一定律;二是从 8.0.31 开始官方把 artifact 改名成了 ​mysql-connector-j​(坐标从 mysql:mysql-connector-java 变成 com.mysql:mysql-connector-j),你照着「找最新版」去翻老路径只会 404。要用新版就得连下载地址和挂载文件名一起换。

第四步:部署 DolphinScheduler

创建 /data/dolphin/docker-compose.yml

services:  dolphinscheduler-standalone:    image: apache/dolphinscheduler-standalone-server:3.2.0    container_name: dolphinscheduler-standalone    # network_mode: "host"  # 放开这行的同时,必须把下面的 extra_hosts 和 ports 一起注释掉    extra_hosts:      - "host.docker.internal:host-gateway"  # Linux 必须加这行,否则容器内无法解析该域名    ports:      - "12345:12345"   # Web UI + API 端口(唯一必须映射的)      - "25333:25333"   # Python 网关端口,只有用 PyDolphinScheduler 写工作流才需要,否则可删    environment:      - TZ=Asia/Shanghai   # 时区,见下方说明      - DATABASE_TYPE=mysql      # 显式声明驱动类名,避免自动推断失败      - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver      # ⚠️ 注意:这里的 IP 要填宿主机的实际 IP 或 host.docker.internal,不能用 127.0.0.1      - SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:13306/ds_scheduler?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true      - SPRING_DATASOURCE_USERNAME=ds_admin      - SPRING_DATASOURCE_PASSWORD=DsPass@2025    volumes:      - /data/dolphin/logs:/opt/dolphinscheduler/logs      # 关键:挂载 MySQL 驱动到容器的 libs 目录      - /data/dolphin/lib/mysql-connector-java-8.0.30.jar:/opt/dolphinscheduler/libs/standalone-server/mysql-connector-java-8.0.30.jar    restart: always

TZ 这行别省。 调度平台跑的全是定时任务:容器默认 UTC,你按北京时间配了「每天凌晨 2 点」,实际会在上午 10 点触发。这种 bug 不报错、不崩溃,只会让数仓数据莫名其妙晚 8 小时——比连不上数据库难查多了。

配好后进容器 date 一下确认:显示 CST 才算生效。

启动:

docker compose up -d

⚠️ 踩坑提醒​:

数据源 URL 中的地址,​千万不能填 ​127.0.0.1​。在容器内部,127.0.0.1 指的是容器自己,不是宿主机。正确做法:

方案 写法 说明
使用宿主机 IP jdbc:mysql://192.168.1.100:13306/ds_scheduler 最通用,Linux/Mac 都行
Docker 特殊域名 jdbc:mysql://host.docker.internal:13306/ds_scheduler Mac/Windows Docker Desktop 原生支持;Linux 需要在 docker-compose.yml 中添加 extra_hosts: ["host.docker.internal:host-gateway"]
宿主机网络模式 放开 network_mode: "host",URL 直接写 127.0.0.1:13306 最省事,但​必须把 portsextra_hosts 两段一起注释掉​——host 模式下容器与宿主机共用网络栈,端口映射不再生效,host.docker.internal 也不需要了

四、验证部署

启动后等待约 30 秒(容器要拉起内置 ZooKeeper 和各个服务),然后浏览器访问:

http://<你的服务器IP>:12345/dolphinscheduler/ui

使用默认账号登录:

用户名 密码
admin dolphinscheduler123

看到登录页面,说明服务已经起来了:

2b11aa6fcda517064cf01ee06351dbab

🔐 登录后第一件事:改密码! 默认密码就像没锁的门,别等被人进来了才后悔。

登录成功后看到首页仪表盘,就说明部署大功告成:

017dac614bcdaec6ca7502e50f754f35

可以试着创建一个简单的 Shell 任务跑个 echo "Hello DolphinScheduler",验证任务调度是否正常。

五、别忘了监控!

单机部署最怕的不是「挂了」,而是「​挂了没人知道​」。

强烈建议配套部署 Prometheus + Grafana 监控方案,做到:

  • 📈 实时掌握任务执行状态
  • 🚨 异常时自动告警(飞书/钉钉/邮件都行)
  • 📊 可视化大盘,随时查看调度平台健康状况

六、后期升级:无缝切换集群模式

可能有同学会担心:「先用单机模式,以后扛不住了怎么办?迁移成本大不大?」

放心,因为我们一开始就选择了 ​MySQL 而非默认的 H2​,所有的工作流定义、任务配置、调度记录、租户信息等数据都持久化在 MySQL 中。后续升级到伪集群或集群模式时:

  1. ​数据完全复用:​新集群的 Master、Worker、API Server 只需指向同一个 MySQL 实例,即可读取到所有历史数据,工作流、定时任务无需重新配置
  2. ​ZooKeeper 换新无影响:​单机模式内置的 ZooKeeper 只负责运行时协调(服务注册发现、Master/Worker 心跳、分布式锁),存的都是临时节点(ephemeral node),不存任何业务数据。切换到外部独立的 ZooKeeper 集群后,各服务启动时会自动重新注册,对工作流和历史数据零影响——相当于换了个新「会议室」,大家重新签个到就行
  3. ​部署流程:​停掉单机容器 → 部署独立 ZooKeeper 集群 → 按集群模式部署多个服务组件 → 连接同一个 MySQL + 新 ZooKeeper → 启动即可
  4. ​零数据迁移:​不需要导出导入,不需要跑迁移脚本,MySQL 里的表结构和数据是通用的

💡 一句话记住这个分工:​MySQL 存的是「记忆」,ZooKeeper 存的是「状态」​。换 ZooKeeper 只是重新握个手,记忆不会丢——这才是本文坚持用 MySQL 替换 H2 的深层原因:​不只为数据安全,更为将来的架构升级留好退路​。

七、总结

项目 说明
部署模式 Docker 单机模式(Standalone)
数据库 MySQL 8.0 替换默认 H2
适用场景 测试环境、中小团队、任务量 < 2000/天
部署耗时 约 10 分钟(不含摸鱼时间)
核心踩坑 1 容器内不能用 127.0.0.1 连宿主机 MySQL
核心踩坑 2 换 MySQL 后不会自动建表,必须先跑官方初始化 SQL
核心踩坑 3 不配 TZ,定时任务会按 UTC 触发、整整错开 8 小时

一句话​:别过度设计。中小团队的离线调度,单机模式 + MySQL + 监控告警,就是性价比最高的方案。等真到了需要集群的那天,再升级也来得及。

📌 如果这篇文章帮你少踩了一个坑,欢迎点赞收藏。毕竟,程序员最大的善良,就是把踩过的坑写成文档。

posted @ 2026-08-26 18:00  海豚调度  阅读(8)  评论(0)    收藏  举报