version: '3.8' services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: astroml-postgres environment: POSTGRES_DB: astroml POSTGRES_USER: astroml POSTGRES_PASSWORD: astroml_password POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C" ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./migrations:/docker-entrypoint-initdb.d networks: - astroml-network healthcheck: test: ["CMD-SHELL", "pg_isready -U astroml -d astroml"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # Redis for caching and job queues redis: image: redis:7-alpine container_name: astroml-redis ports: - "6379:6379" volumes: - redis_data:/data networks: - astroml-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped command: redis-server --appendonly yes # FastAPI REST API Service api: build: context: . dockerfile: api/Dockerfile container_name: astroml-api environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - LOG_LEVEL=INFO - ASTROML_ENV=container - SECRET_KEY=${SECRET_KEY:-dev-secret-key-change-in-production} - JWT_SECRET_KEY=${JWT_SECRET_KEY:-dev-jwt-secret-key-change-in-production} ports: - "8000:8000" volumes: - ./config:/app/config:ro - api_logs:/app/logs networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s restart: unless-stopped # Celery worker — issue #296 celery-worker: build: . command: celery -A astroml.tasks.celery_app worker --loglevel=info environment: - CELERY_BROKER_URL=redis://redis:6379/0 - CELERY_RESULT_BACKEND=redis://redis:6379/0 networks: - astroml-network depends_on: redis: condition: service_healthy restart: unless-stopped # Flower — Celery monitoring UI — issue #296 flower: build: . command: celery -A astroml.tasks.celery_app flower --port=5555 ports: - "5555:5555" networks: - astroml-network depends_on: - celery-worker restart: unless-stopped # Feature Store Service feature-store: build: context: . target: feature-store container_name: astroml-feature-store environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - LOG_LEVEL=INFO - ASTROML_ENV=container ports: - "8000:8000" - "8080:8080" volumes: - feature_store_data:/app/feature_store - feature_store_logs:/app/logs - ./config:/app/config:ro networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped profiles: - feature-store - full # Ingestion Service ingestion: build: context: . target: ingestion container_name: astroml-ingestion environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - LOG_LEVEL=INFO - STELLAR_NETWORK_PASSPHRASE=Public Global Stellar Network ; September 2015 - ASTROML_ENV=container ports: - "8001:8000" - "8081:8080" volumes: - ./config:/app/config:ro - ingestion_logs:/app/logs - ingestion_data:/app/data - feature_store_data:/app/feature_store networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy feature-store: condition: service_started restart: unless-stopped command: ["python", "-m", "astroml.ingestion"] # Enhanced Streaming Service streaming: build: context: . target: ingestion container_name: astroml-streaming environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - LOG_LEVEL=INFO - STELLAR_HORIZON_URL=https://horizon.stellar.org - STELLAR_NETWORK_PASSPHRASE=Public Global Stellar Network ; September 2015 - ASTROML_ENV=container ports: - "8002:8000" volumes: - ./config:/app/config:ro - streaming_logs:/app/logs - feature_store_data:/app/feature_store networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy feature-store: condition: service_started restart: unless-stopped command: ["python", "-m", "astroml.ingestion.enhanced_stream"] # Training Service (GPU-enabled) training-gpu: build: context: . target: training container_name: astroml-training-gpu environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - CUDA_VISIBLE_DEVICES=0 - PYTHONPATH=/app - ASTROML_ENV=container ports: - "6006:6006" # TensorBoard volumes: - ./config:/app/config:ro - training_models:/app/models - training_data:/app/data - training_logs:/app/logs - feature_store_data:/app/feature_store networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy feature-store: condition: service_started restart: "no" # Training jobs are typically run once profiles: - gpu - full deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] # Training Service (CPU-only) training-cpu: build: context: . target: training-cpu container_name: astroml-training-cpu environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - PYTHONPATH=/app - ASTROML_ENV=container ports: - "6007:6006" # TensorBoard volumes: - ./config:/app/config:ro - training_models:/app/models - training_data:/app/data - training_logs:/app/logs - feature_store_data:/app/feature_store networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy feature-store: condition: service_started restart: "no" profiles: - cpu - full # Development Environment dev: build: context: . target: development container_name: astroml-dev environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - PYTHONPATH=/app - ASTROML_ENV=container ports: - "8003:8000" - "8888:8888" # Jupyter - "6008:6006" # TensorBoard volumes: - .:/app - dev_logs:/app/logs - dev_data:/app/data - feature_store_data:/app/feature_store networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy feature-store: condition: service_started restart: unless-stopped profiles: - dev - full command: ["jupyter", "lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root"] # Production Service production: build: context: . target: production container_name: astroml-production environment: - DATABASE_URL=postgresql://astroml:astroml_password@postgres:5432/astroml - REDIS_URL=redis://redis:6379/0 - FEATURE_STORE_PATH=/app/feature_store - LOG_LEVEL=WARNING - ASTROML_ENV=container ports: - "8004:8000" volumes: - ./config:/app/config:ro - production_logs:/app/logs - production_data:/app/data - feature_store_data:/app/feature_store networks: - astroml-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy feature-store: condition: service_started restart: unless-stopped profiles: - prod - full # Monitoring with Prometheus (optional) prometheus: image: prom/prometheus:latest container_name: astroml-prometheus ports: - "9090:9090" volumes: - ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./monitoring/prometheus/alert_rules.yml:/etc/prometheus/alert_rules.yml:ro - prometheus_data:/prometheus networks: - astroml-network profiles: - monitoring restart: unless-stopped # Grafana for visualization (optional) grafana: image: grafana/grafana:latest container_name: astroml-grafana environment: - GF_SECURITY_ADMIN_PASSWORD=admin ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana - ./monitoring/grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards:ro - ./monitoring/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro networks: - astroml-network depends_on: - prometheus profiles: - monitoring restart: unless-stopped # Soroban Contract Development soroban-dev: build: context: . dockerfile: Dockerfile.soroban target: development container_name: astroml-soroban-dev environment: - RUST_BACKTRACE=1 - CARGO_TERM_COLOR=always ports: - "8000:8000" volumes: - ./src:/app/src - ./Cargo.toml:/app/Cargo.toml - ./Cargo.lock:/app/Cargo.lock - soroban_target:/app/target - soroban_logs:/app/logs networks: - astroml-network restart: unless-stopped profiles: - soroban # Soroban Contract Build soroban-build: build: context: . dockerfile: Dockerfile.soroban target: build container_name: astroml-soroban-build volumes: - ./src:/app/src - ./Cargo.toml:/app/Cargo.toml - ./Cargo.lock:/app/Cargo.lock - soroban_wasm:/app/target/wasm networks: - astroml-network profiles: - soroban-build # Soroban Contract Testing soroban-test: build: context: . dockerfile: Dockerfile.soroban target: testing container_name: astroml-soroban-test environment: - RUST_BACKTRACE=1 volumes: - ./src:/app/src - ./Cargo.toml:/app/Cargo.toml - ./Cargo.lock:/app/Cargo.lock - soroban_target:/app/target networks: - astroml-network profiles: - soroban-test networks: astroml-network: driver: bridge volumes: postgres_data: driver: local redis_data: driver: local feature_store_data: driver: local feature_store_logs: driver: local ingestion_logs: driver: local ingestion_data: driver: local streaming_logs: driver: local training_models: driver: local training_data: driver: local training_logs: driver: local dev_logs: driver: local dev_data: driver: local production_logs: driver: local production_data: driver: local prometheus_data: driver: local grafana_data: driver: local soroban_target: driver: local soroban_wasm: driver: local soroban_logs: driver: local api_logs: driver: local