
点亮⭐️
https://github.com/apache/
点击蓝字 关注我们
摘要: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) | ||
| 伪集群模式(Pseudo-Cluster) | ||
| 集群模式(Cluster) |
一句话总结:小团队用单机模式就够了——而且只要按本文的方式换掉默认数据库,将来升级集群是零数据迁移的(§六 会展开)。
二、为什么选单机模式?
网上铺天盖地的集群部署教程,看着就头大——3 台机器起步、ZooKeeper 集群、MySQL 主从……
打住! 你确定你的场景需要这么重?
以我的实际业务为例:
更关键的是——离线数仓场景下,即使 DolphinScheduler 短暂挂掉,对线上业务零影响。任务晚跑几分钟,数据不会丢,天不会塌。
核心思路:在单机模式基础上,用 MySQL 替换默认的 H2 数据库。注意 standalone 默认那个 H2 走的是 jdbc:h2:mem: ——纯内存,不是「可能丢数据」,是容器一重启工作流定义、调度记录全部归零。拿它跑生产,等于把家当放在断电就清空的柜子里。换成 MySQL,数据持久化才谈得上安心。
另一个好处是:数据存在 MySQL 后,DolphinScheduler 本身可以随时重建。后续如果需要集成插件、自定义镜像,直接重新部署容器,连上同一个 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_passwordcaching_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_definition、t_ds_worker_group 等一系列表。如果输出为空,检查上一步 SQL 执行有没有报错。
⚡ 这一步别跳过! 换成 MySQL 之后没有任何自动建表——H2 模式下开箱即用的那套初始化不会发生。跳过的后果就是启动后喜提 Table 'xxx' doesn't exist。
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。要用新版就得连下载地址和挂载文件名一起换。
创建 /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 指的是容器自己,不是宿主机。正确做法:
jdbc:mysql://192.168.1.100:13306/ds_scheduler | ||
jdbc:mysql://host.docker.internal:13306/ds_scheduler | extra_hosts: ["host.docker.internal:host-gateway"] | |
network_mode: "host",URL 直接写 127.0.0.1:13306 | ports 和 extra_hosts 两段一起注释掉——host 模式下容器与宿主机共用网络栈,端口映射不再生效,host.docker.internal 也不需要了 |
四、验证部署
启动后等待约 30 秒(容器要拉起内置 ZooKeeper 和各个服务),然后浏览器访问:
http://<你的服务器IP>:12345/dolphinscheduler/ui使用默认账号登录:
admin | dolphinscheduler123 |
看到登录页面,说明服务已经起来了:

登录后第一件事:改密码! 默认密码就像没锁的门,别等被人进来了才后悔。
登录成功后看到首页仪表盘,就说明部署大功告成:

可以试着创建一个简单的 Shell 任务跑个 echo "Hello DolphinScheduler",验证任务调度是否正常。
五、别忘了监控!
单机部署最怕的不是「挂了」,而是「挂了没人知道」。
强烈建议配套部署 Prometheus + Grafana 监控方案,做到:
六、后期升级:无缝切换集群模式
可能有同学会担心:「先用单机模式,以后扛不住了怎么办?迁移成本大不大?」
放心,因为我们一开始就选择了 MySQL 而非默认的 H2,所有的工作流定义、任务配置、调度记录、租户信息等数据都持久化在 MySQL 中。后续升级到伪集群或集群模式时:
一句话记住这个分工:MySQL 存的是「记忆」,ZooKeeper 存的是「状态」。换 ZooKeeper 只是重新握个手,记忆不会丢——这才是本文坚持用 MySQL 替换 H2 的深层原因:不只为数据安全,更为将来的架构升级留好退路。
七、总结
127.0.0.1 连宿主机 MySQL | |
TZ,定时任务会按 UTC 触发、整整错开 8 小时 |
一句话:别过度设计。中小团队的离线调度,单机模式 + MySQL + 监控告警,就是性价比最高的方案。等真到了需要集群的那天,再升级也来得及。
如果这篇文章帮你少踩了一个坑,欢迎点赞收藏。毕竟,程序员最大的善良,就是把踩过的坑写成文档。
END

用户案例

迁移实战

最新发版消息

加入社区
关注社区的方式有很多:
同样地,参与Apache DolphinScheduler 有非常多的参与贡献的方式,主要分为代码方式和非代码方式两种。
非代码方式包括:
完善文档、翻译文档;翻译技术性、实践性文章;投稿实践性、原理性文章;成为布道师;社区管理、答疑;会议分享;测试反馈;用户反馈等。
代码方式包括:
查找Bug;编写修复代码;开发新功能;提交代码贡献;参与代码审查等。


你的好友小海豚拍了拍你
并请你帮她点一下“分享”
