4、环境搭建:使用 Docker Compose 部署 Dagster 全家桶(Dagit、Daemon、Postgres)
说实话,很多初学者在 Dagster 上栽的第一个跟头,不是代码写错了,而是环境没搭好。我见过太多人花了一整天在本地装依赖、配 Python 版本、调数据库驱动……最后心态崩了。
我个人习惯,但凡涉及多服务协作的项目,一律用 Docker Compose。你想想看,Dagster 全家桶至少包含三个组件:Dagit(Web UI)、Daemon(调度守护进程)、Postgres(持久化存储)。手动配?太累了。用 Compose 一条命令搞定,不香吗?
为什么非要用 Docker Compose?
Dagster 的架构其实挺清晰的,但服务一多,依赖关系就复杂了。我画了张图,你看一眼就明白:
说白了,Dagit 是门面,Daemon 是后台苦力,Postgres 是仓库。三者缺一不可。
第一步:准备项目目录结构
我习惯把项目文件组织得干净一点。你跟着我来:
dagster-project/
├── dagster.yaml # Dagster 实例配置
├── workspace.yaml # 代码仓库配置
├── docker-compose.yml # 服务编排文件
├── Dockerfile # 自定义镜像(可选)
└── my_dagster_project/ # 你的管道代码
├── __init__.py
├── assets.py
└── schedules.py
嗯,这里要注意:workspace.yaml 是 Dagster 1.0 之后才强制的。老版本可能不需要,但新项目我建议直接上。
第二步:编写 docker-compose.yml
这是核心。我直接给你一个我生产环境验证过的版本:
version: "3.8"
services:
postgres:
image: postgres:14
environment:
POSTGRES_USER: dagster
POSTGRES_PASSWORD: dagster
POSTGRES_DB: dagster
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dagster"]
interval: 10s
timeout: 5s
retries: 5
dagit:
build: .
ports:
- "3000:3000"
environment:
DAGSTER_HOME: /opt/dagster
volumes:
- .:/opt/dagster
depends_on:
postgres:
condition: service_healthy
command: dagit -h 0.0.0.0 -p 3000
daemon:
build: .
environment:
DAGSTER_HOME: /opt/dagster
volumes:
- .:/opt/dagster
depends_on:
postgres:
condition: service_healthy
command: dagster-daemon run
volumes:
postgres_data:
healthcheck,结果 Dagit 启动时 Postgres 还没就绪,直接报连接拒绝。加了 healthcheck 和 condition: service_healthy 之后,世界清净了。
第三步:配置 dagster.yaml
这个文件告诉 Dagster 怎么连数据库。我一般这样写:
storage:
postgres:
postgres_db:
username: dagster
password: dagster
hostname: postgres
db_name: dagster
port: 5432
run_launcher:
module: dagster.core.launcher
class: DefaultRunLauncher
scheduler:
module: dagster.core.scheduler
class: DagsterDaemonScheduler
hostname 写的是 postgres,不是 localhost。因为在 Docker 网络里,服务名就是主机名。我第一次写 localhost 时,容器内部根本连不上——它以为自己在找本机的 5432 端口。
第四步:配置 workspace.yaml
这个文件告诉 Dagit 去哪里加载你的管道代码:
load_from:
- python_module:
module_name: my_dagster_project
working_directory: /opt/dagster
说白了,就是告诉 Dagster:「嘿,去 my_dagster_project 这个 Python 包里找你的 Job 和 Asset。」
第五步:编写 Dockerfile
如果你不想每次都 build 镜像,也可以用现成的 dagster/dagster 镜像。但我个人习惯自己写一个,方便装额外依赖:
FROM python:3.9-slim
WORKDIR /opt/dagster
RUN pip install dagster dagit dagster-postgres
COPY . .
RUN pip install -e .
pip install -e . 这步很重要。它把你的项目以可编辑模式安装,这样你改代码后不用重新 build 镜像。开发阶段能省不少时间。
第六步:启动全家桶
所有文件就位后,一条命令搞定:
docker-compose up -d
等个十几秒,打开浏览器访问 http://localhost:3000,你应该能看到 Dagit 的界面了。
如果页面没出来,别慌。先看看日志:
docker-compose logs -f dagit
常见的错误无非两种:
- Postgres 连不上 —— 检查
dagster.yaml里的 hostname 是不是postgres - 代码加载失败 —— 检查
workspace.yaml里的 module_name 对不对
各组件端口一览
为了方便你排查,我把端口整理了一下:
| 组件 | 内部端口 | 外部映射端口 | 说明 |
|---|---|---|---|
| Dagit | 3000 | 3000 | Web UI,浏览器访问 |
| Daemon | 无 | 无 | 后台进程,无需暴露端口 |
| Postgres | 5432 | 5432 | 数据库,可用 Navicat 等工具连接 |
docker-compose.yml 里写 ports: - "5432:5432" 是为了开发调试方便。上线前记得删掉。
验证部署是否成功
打开 Dagit 后,你会看到一个空的工作台。别急,这说明环境搭好了。你可以手动触发一个测试:
- 点击左侧的 Launchpad
- 选择一个 Job(如果你还没写,可以先创建一个简单的)
- 点击 Launch Run
如果运行记录出现在 Runs 页面,恭喜你,全家桶跑通了。
嗯,我记得第一次搭好环境时,看到 Dagit 页面里那个绿色的「Success」标记,心里特别踏实。环境搭好了,后面写代码才有底气。