Skip to content

Deployment Guide: Docker Compose Stack

Overview

Phoenix ML deploys via Docker Compose with 14+ containers, or Kubernetes via Helm chart.

Quick Start

# 1. Clone & config
git clone https://github.com/vtnguyen04/phoenix_ML.git
cd phoenix_ML
cp .env.example .env

# 2. Start infrastructure services
docker compose up -d

# 3. Start Airflow (optional)
docker compose -f docker-compose.airflow.yaml up -d

# 4. Generate data & train models
uv run python scripts/generate_datasets.py
uv run python examples/credit_risk/train.py

# 5. Verify
curl http://localhost:8001/health
# → {"status": "healthy", "version": "1.0.0"}

Service Architecture

docker-compose.yaml — Core Services

graph LR
    subgraph SG_Frontend ["Frontend"]
        FE["phoenix-frontend<br/>:5174"]
    end

    subgraph SG_API ["API"]
        API["phoenix-api<br/>:8001 + :50051 gRPC"]
    end

    subgraph SG_Data ["Data"]
        PG["postgres<br/>:5433"]
        RD["redis<br/>:6380"]
    end

    subgraph SG_Messaging ["Messaging"]
        KF["kafka<br/>:9094"]
        KUI["kafka-ui<br/>:8082"]
    end

    subgraph SG_ML ["ML"]
        MLF["mlflow<br/>:5001"]
        MINIO["minio<br/>:9000"]
    end

    subgraph SG_Monitoring ["Monitoring"]
        PROM["prometheus<br/>:9091"]
        GRAF["grafana<br/>:3001"]
        JAEG["jaeger<br/>:16686"]
    end

    FE --> API
    API --> PG
    API --> RD
    API --> KF
    API --> MLF
    API --> PROM
    API --> JAEG
    KUI --> KF
    PROM --> GRAF
    MLF --> MINIO

Service Details

Service Image Internal Port External Port Volume Mounts Health Check
phoenix-api Build from Dockerfile 8000 8001 ./src, ./models, ./data, ./model_configs /health
phoenix-frontend Build from Dockerfile.frontend 5173 5174 ./frontend/src —
postgres postgres:15-alpine 5432 5433 pgdata volume pg_isready
redis redis:7-alpine 6379 6380 redis_data volume redis-cli ping
kafka apache/kafka:latest 9092 9094 kafka_data volume —
kafka-ui provectuslabs/kafka-ui 8080 8082 — —
mlflow ghcr.io/mlflow/mlflow 5000 5001 mlflow_data volume —
prometheus prom/prometheus 9090 9091 ./prometheus.yml —
grafana grafana/grafana 3000 3001 ./grafana/ —
jaeger jaegertracing/all-in-one 16686 16686 — —
minio minio/minio 9000/9001 9000/9001 minio_data volume —

docker-compose.airflow.yaml — Airflow Stack

Service Image Port Purpose
airflow-webserver Build from Dockerfile.airflow 8080 Airflow Web UI
airflow-scheduler Build from Dockerfile.airflow — DAG scheduling
airflow-init Build from Dockerfile.airflow — Init DB + admin user (admin/admin)
postgres-airflow postgres:15-alpine 5432 Airflow metadata DB

Environment Variables (.env)

# ── Database ──
DATABASE_URL=postgresql+asyncpg://phoenix:phoenix@postgres:5432/phoenix
TEST_DATABASE_URL=sqlite+aiosqlite:///./phoenix_test.db

# ── Redis ──
REDIS_URL=redis://redis:6379

# ── Kafka ──
KAFKA_URL=kafka:9092

# ── MLflow ──
MLFLOW_TRACKING_URI=http://mlflow:5000

# ── Model Config ──
DEFAULT_MODEL_ID=credit-risk
DEFAULT_MODEL_VERSION=v1
MODEL_CONFIG_DIR=model_configs
INFERENCE_ENGINE=onnx

# ── Monitoring ──
MONITORING_INTERVAL_SECONDS=30
DRIFT_THRESHOLD=0.3

# ── Storage ──
ARTIFACT_STORAGE_DIR=./artifacts
CACHE_DIR=./cache

# ── Ports ──
API_PORT=8001
FRONTEND_PORT=5174

Makefile Commands

make up          # docker compose up -d
make down        # docker compose down
make build       # docker compose build
make restart     # down + up
make logs        # docker compose logs -f
make ps          # docker compose ps
make clean       # down -v (remove volumes)
make test        # uv run pytest
make api-logs    # docker compose logs -f phoenix-api
make frontend-logs  # docker compose logs -f phoenix-frontend

Training Pipeline

Training is managed via Airflow DAG (dags/retrain_pipeline.py) or direct scripts:

# Generate data + train all models
uv run python scripts/generate_datasets.py
uv run python examples/credit_risk/train.py
uv run python examples/house_price/train.py
uv run python examples/fraud_detection/train.py
uv run python examples/image_classification/train.py
uv run python examples/sentiment/train.py

# Run end-to-end simulation
uv run python scripts/simulate_pipeline.py --fast

# Or trigger via Airflow UI (http://localhost:8080)

Kubernetes Deployment (Helm)

# Install via Helm
helm install phoenix-ml deploy/helm/phoenix-ml/

# Custom values
helm install phoenix-ml deploy/helm/phoenix-ml/ \
  --set replicaCount=3 \
  --set image.tag=v1.0.0 \
  --set resources.limits.memory=2Gi

# Upgrade
helm upgrade phoenix-ml deploy/helm/phoenix-ml/

# Uninstall
helm uninstall phoenix-ml

Helm Chart Structure

deploy/helm/phoenix-ml/
├── Chart.yaml              # name: phoenix-ml, version: 0.1.0
├── values.yaml             # Default: 1 replica, 512Mi memory
└── templates/
    ├── deployment.yaml     # Pod spec, health probes, env vars
    ├── service.yaml        # ClusterIP on port 8000
    ├── ingress.yaml        # External access, TLS
    └── hpa.yaml            # Auto-scale: 1-10 replicas, 80% CPU target

Database Migrations

# Apply all migrations
uv run alembic upgrade head

# Create new migration
uv run alembic revision --autogenerate -m "add new table"

# Rollback last migration
uv run alembic downgrade -1

# View current version
uv run alembic current

Schema

models
├── id (VARCHAR, PK)
├── version (VARCHAR, PK)
├── uri (VARCHAR)
├── framework (VARCHAR)
├── stage (VARCHAR: champion/challenger/retired/archived)
├── metadata_json (JSONB)
├── metrics_json (JSONB)
├── is_active (BOOLEAN)
└── created_at (TIMESTAMP)

prediction_logs
├── id (UUID, PK)
├── model_id (VARCHAR)
├── model_version (VARCHAR)
├── features_json (JSONB)
├── result (FLOAT)
├── confidence (FLOAT)
├── latency_ms (FLOAT)
├── ground_truth (FLOAT, nullable)
└── timestamp (TIMESTAMP)

drift_reports
├── id (UUID, PK)
├── model_id (VARCHAR)
├── feature_name (VARCHAR)
├── method (VARCHAR: ks/psi/chi2)
├── score (FLOAT)
├── is_drifted (BOOLEAN)
├── threshold (FLOAT)
└── timestamp (TIMESTAMP)

Grafana (Auto-provisioned)

Dashboards and datasources auto-provisioned on startup:

  • Datasource: Prometheus (http://prometheus:9090)
  • Dashboard: phoenix-ml.json — panels: prediction count, latency histogram, drift score, model accuracy

Access: http://localhost:3001 (admin/admin)

Port Summary

Port Service Protocol
5174 Frontend (React) HTTP
8001 API (FastAPI) HTTP
50051 gRPC Server gRPC
5433 PostgreSQL TCP
6380 Redis TCP
9094 Kafka TCP
8082 Kafka UI HTTP
5001 MLflow HTTP
9091 Prometheus HTTP
3001 Grafana HTTP
16686 Jaeger HTTP
9000 MinIO (API) HTTP
9001 MinIO (Console) HTTP
8080 Airflow HTTP

Document Status: v4.0 — Updated March 2026