Dagsterの実験記録にMLflowとMinIOを追加
AIシステム開発の実験追跡用に、DagsterのdevstackへMLflowとMinIOを追加しました。correlation_id連携、ポート衝突、PostgreSQLドライバ不足、既存DBへの追加を扱います。
MLflowとMinIOを追加
Dagster + NATS イベントパイプラインが動くdevstackに、MLflow Tracking ServerとMinIOを追加しました。Dagsterは処理全体、MLflowは個々の実験を記録し、correlation_idで結びます。AIシステム開発の実験を追跡する基盤です。
8ファイルを変更し、MinIO、minio-init、MLflowの3サービスを追加しました。AirPlayのポート衝突、psycopg2不足、既存PostgreSQLへのDB追加を修正して起動しています。
なぜ MLflow が必要になったか
DagsterはNATS JetStreamからイベントをpullし、sensorでジョブを起動してPostgreSQLへ保存していました。個々の実験のパラメータ、メトリクス、アーティファクトを追う機能としてMLflowを加えます。
観測の役割を分けます。
- Dagster: 俯瞰ビュー(何が起きたか)
- MLflow: 詳細ビュー(中で何が起きたか)
correlation_idで両者を紐づける- Dagster asset metadata に
experiment_id,run_id,tracker_url,summaryを記録 - MLflow run の tags に
correlation_idを設定
Phase 2以降のfine-tuningと投資予測モデル生成に備えた構成です。
既存インフラの構成
devstack 全体の構成は以下の通り。
Core サービス:
| サービス | 役割 |
|---|---|
| NATS (JetStream) | メッセージング |
| PostgreSQL 18 (pgvector + JIT, 4GB SHM) | データストア |
| Dagster 3コンテナ (webserver + daemon + user-code gRPC) | オーケストレーション |
| Vector | テレメトリ収集 |
| FastAPI Reranker (ColBERT) | リランキング |
Lakehouse profile(オプション): Nessie、Trino、dbt-fusion
3ホスト構成:
- storage server
- desktop mac — NATS を配置し gateway と同居
- compute server — Dagster と PostgreSQL を配置
READMEにはMinIOによるバイナリ保存方針がありましたが、podman-compose.ymlにサービスはありませんでした。MLflowのS3互換artifact storeとして追加します。
変更計画
podman-compose.ymlに MLflow Tracking Server を追加。backend store は既存 PostgreSQL に mlflow DB を追加して流用、artifact store は MinIO のs3://mlflow/を使うinit.sqlにCREATE DATABASE mlflow;を追加- Dagster 側に
dagster-mlflowresource を追加し、experiment_nameとmlflow_tracking_uriを設定可能にする - 環境変数に
MLFLOW_TRACKING_URIとMLFLOW_S3_ENDPOINT_URLを追加 README.mdを更新
実験記録はMLflow、オーケストレーションはDagsterです。
dagster-mlflow の API 調査
Dagsterは1.12.14に固定されているため、対応バージョンを確認しました。
dagster 1.12.Xにはdagster-mlflow 0.28.Xが対応します。今回はdagster-mlflow==0.28.14を使い、依存はdagster==1.12.14、mlflow、pandas<3.0.0、protobuf!=5.29.0です。
一時venvにインストールし、ソースで確認しました。
mlflow_trackingは old-style の@resourceデコレータによるResourceDefinition。既存のPostgresResourceやEmbeddingResourceが使っているConfigurableResourceパターンではない- ops から使うには
required_resource_keys={"mlflow"}を指定してcontext.resources.mlflowでアクセスする end_mlflow_on_run_finishedフックを job に適用しないと MLflow run がハング状態になる。これは必須MlflowMetaメタクラスがmlflow.*の全メソッドをプロキシするため、resource オブジェクトから直接log_params(),log_metric(),log_artifact()を呼べるenvconfig で S3 認証情報を渡せるが、コンテナ環境変数として設定済みなら不要
dagster-mlflowは既存コードと異なるold-style resourceを使うパッケージです。
実装
8ファイルを変更・追加しました。
podman-compose.yml: 3サービス追加
MinIO(docker.io/minio/minio:latest)を9000/9001とminio-data volumeで追加しました。minio-initはmcでs3://mlflow/を作るone-shotコンテナです。
MLflow Tracking Server (ghcr.io/mlflow/mlflow:v2.21.3, port 5000):
--backend-store-uri=postgresql://postgres:postgres@postgres:5432/mlflow
--default-artifact-root=s3://mlflow/
backend storeはPostgreSQL、artifact storeはMinIOです。depends_onでpostgresのservice_healthyとminio-initのservice_completed_successfullyを待ちます。
dagster-user-codeとdagster-daemonに環境変数を追加します。
MLFLOW_TRACKING_URI: "http://mlflow:5000"
MLFLOW_S3_ENDPOINT_URL: "http://minio:9000"
AWS_ACCESS_KEY_ID: minioadmin
AWS_SECRET_ACCESS_KEY: minioadmin
init.sql
CREATE DATABASE mlflow;
dagster/pyproject.toml
dagster-mlflow==0.28.14と、S3アクセス用のboto3を追加しました。
dagster/project/resources/mlflow.py(新規)
mlflow_tracking.configured({
"experiment_name": os.getenv("MLFLOW_EXPERIMENT_NAME", "agent-gateway"),
"mlflow_tracking_uri": os.getenv("MLFLOW_TRACKING_URI", "http://mlflow:5000"),
"extra_tags": {"project": "agent-gateway"},
})
dagster/project/defs.py
Definitionsのresourcesへ"mlflow": mlflow_resourceを追加しました。
.envrc
MLFLOW_TRACKING_URIとMLFLOW_S3_ENDPOINT_URLを追加しました。
トラブルシューティング
ポート 5000 の衝突
podman compose up -d mlflowで起動に失敗しました。
Error response from daemon: "listen tcp :5000: bind: address already in use"
lsof -i :5000で、macOS ControlCenterのAirPlay Receiverが5000を使用していると分かりました。
ホストの割り当てを"${MLFLOW_PORT:-5050}:5000"へ変更しました。内部は5000のままなので、DagsterのMLFLOW_TRACKING_URI: http://mlflow:5000 も維持します。ホストからは5050です。
内部のMLFLOW_TRACKING_URIも一度5050に変えましたが、コンテナ間通信のため5000へ戻しました。.envrcはMLFLOW_PORT="5050"と"http://${COMPUTE_HOST}:${MLFLOW_PORT}"を外部アクセスに使います。
公式イメージに psycopg2 がない
ポート修正後も、起動直後にクラッシュしました。
ModuleNotFoundError: No module named 'psycopg2'
使用したghcr.io/mlflow/mlflow:v2.21.3にpsycopg2がありませんでした。SQLite/MySQLを想定したイメージのため、PostgreSQLドライバを追加します。
devstack/mlflow/Dockerfileを追加しました。
FROM ghcr.io/mlflow/mlflow:v2.21.3
RUN pip install --no-cache-dir psycopg2-binary boto3
podman-compose.ymlのimage:指定をbuild: context: ./devstack/mlflowへ変更し、image: localhost/agent-gateway/mlflow:2.21.3を付けました。
既存ボリュームへの DB 追加
再ビルド後はPostgreSQLのエラーでした。
FATAL: database "mlflow" does not exist
init.sqlにCREATE DATABASE mlflow;を追加しても、docker-entrypoint-initdb.dは初回にしか動きません。3週間前からあるpostgres-dataには反映されませんでした。
DBを手動作成しました。
podman exec agent-gateway-postgres-1 psql -U postgres -c "CREATE DATABASE mlflow;"
init.sqlの追加は、新規構築やボリューム再作成時のために残します。
結果
Alembicマイグレーション後、gunicornが4ワーカーで起動しました。
[2026-03-12 02:07:58 +0000] [24] [INFO] Starting gunicorn 23.0.0
[2026-03-12 02:07:58 +0000] [24] [INFO] Listening at: http://0.0.0.0:5000 (24)
experiments/searchでDefault experimentを確認しました。artifact_locationはs3://mlflow/0でMinIOを参照しています。
変更ファイル一覧
| ファイル | 変更内容 |
|---|---|
podman-compose.yml | MinIO, minio-init, mlflow の3サービス追加 + Dagster 環境変数追加 |
devstack/postgres/init.sql | CREATE DATABASE mlflow |
devstack/dagster/pyproject.toml | dagster-mlflow==0.28.14, boto3 追加 |
devstack/dagster/project/resources/mlflow.py | 新規: mlflow_tracking configured resource |
devstack/dagster/project/defs.py | mlflow resource 登録 |
devstack/mlflow/Dockerfile | 新規: psycopg2-binary + boto3 追加 |
.envrc | MLFLOW_PORT, MLFLOW_TRACKING_URI, MLFLOW_S3_ENDPOINT_URL |
README.md | サービス一覧、環境変数、トポロジー図更新 |
設計上の注意点
dagster-mlflowは old-style resource(@resourceデコレータ)であり、ConfigurableResourceではない。job に@end_mlflow_on_run_finishedフックを必ず適用すること- コンテナ間通信は内部ポート 5000、ホストからのアクセスはポート 5050(macOS AirPlay Receiver 回避)
- PostgreSQL ボリュームが既存の場合、
init.sqlの新規 DB 作成は手動で反映が必要
