version: '3.8' # Production Docker Compose Stack for Foxhunt HFT Trading System # Wave 71 Agent 8: Complete production deployment configuration # # Agent S8: Production Password Generator # All passwords are sourced from HashiCorp Vault # # Usage: # 1. Generate passwords: ./scripts/setup_production_passwords.sh # 2. Export environment variables: source ./scripts/export_vault_passwords.sh # 3. Deploy: docker-compose -f docker-compose.production.yml up -d # # Environment variables required from Vault: # - POSTGRES_PASSWORD (from secret/postgres) # - REDIS_PASSWORD (from secret/redis) # - INFLUXDB_PASSWORD (from secret/influxdb) # - VAULT_ROOT_TOKEN (from secret/vault) # - GRAFANA_PASSWORD (from secret/grafana) # Define custom networks for isolation and controlled access networks: foxhunt_internal: driver: bridge ipam: config: - subnet: 172.20.0.0/16 foxhunt_external: driver: bridge # Define named volumes for persistent data volumes: postgres_data: redis_data: influxdb_data: vault_data: prometheus_data: grafana_data: services: # ============================================================================= # Infrastructure Services # ============================================================================= postgres: image: postgres:16-alpine container_name: foxhunt-postgres restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-foxhunt} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-foxhunt} POSTGRES_INITDB_ARGS: "-E UTF8 --locale=C" volumes: - postgres_data:/var/lib/postgresql/data - ./database/migrations:/docker-entrypoint-initdb.d:ro networks: foxhunt_internal: ipv4_address: 172.20.0.10 healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-foxhunt} -d ${POSTGRES_DB:-foxhunt}"] interval: 5s timeout: 3s retries: 5 start_period: 10s deploy: resources: limits: cpus: '2.0' memory: 2G reservations: cpus: '1.0' memory: 1G redis: image: redis:7-alpine container_name: foxhunt-redis restart: unless-stopped command: > sh -c "redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru --appendonly yes $([ -n \"${REDIS_PASSWORD}\" ] && echo \"--requirepass ${REDIS_PASSWORD}\" || echo \"\")" volumes: - redis_data:/data networks: foxhunt_internal: ipv4_address: 172.20.0.11 healthcheck: test: ["CMD", "sh", "-c", "redis-cli $([ -n \"${REDIS_PASSWORD}\" ] && echo \"--pass ${REDIS_PASSWORD}\" || echo \"\") ping"] interval: 5s timeout: 3s retries: 5 start_period: 10s deploy: resources: limits: cpus: '1.0' memory: 512M reservations: cpus: '0.5' memory: 256M influxdb: image: influxdb:2.7-alpine container_name: foxhunt-influxdb restart: unless-stopped environment: DOCKER_INFLUXDB_INIT_MODE: setup DOCKER_INFLUXDB_INIT_USERNAME: ${INFLUXDB_USER:-admin} DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_PASSWORD} DOCKER_INFLUXDB_INIT_ORG: ${INFLUXDB_ORG:-foxhunt} DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUXDB_BUCKET:-trading_metrics} DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_ADMIN_TOKEN} DOCKER_INFLUXDB_INIT_RETENTION: ${INFLUXDB_RETENTION:-30d} volumes: - influxdb_data:/var/lib/influxdb2 networks: foxhunt_internal: ipv4_address: 172.20.0.12 healthcheck: test: ["CMD", "influx", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 30s deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.5' memory: 512M vault: image: hashicorp/vault:1.15 container_name: foxhunt-vault restart: unless-stopped environment: VAULT_ADDR: http://0.0.0.0:8200 VAULT_API_ADDR: http://0.0.0.0:8200 # Production: Remove VAULT_DEV_ROOT_TOKEN_ID and use proper initialization VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_ROOT_TOKEN} cap_add: - IPC_LOCK volumes: - vault_data:/vault/file networks: foxhunt_internal: ipv4_address: 172.20.0.13 command: vault server -dev -dev-listen-address=0.0.0.0:8200 healthcheck: test: ["CMD", "vault", "status"] interval: 10s timeout: 5s retries: 5 start_period: 15s deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.25' memory: 128M prometheus: image: prom/prometheus:v2.48.0 container_name: foxhunt-prometheus restart: unless-stopped volumes: - ./config/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./config/prometheus/rules:/etc/prometheus/rules:ro - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention.time=30d' - '--web.enable-lifecycle' - '--query.max-concurrency=50' networks: foxhunt_internal: ipv4_address: 172.20.0.14 healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/ready"] interval: 10s timeout: 5s retries: 5 start_period: 15s deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.5' memory: 512M grafana: image: grafana/grafana:10.2.3 container_name: foxhunt-grafana restart: unless-stopped environment: GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD} # From Vault: secret/grafana GF_INSTALL_PLUGINS: grafana-piechart-panel GF_SERVER_ROOT_URL: ${GRAFANA_ROOT_URL:-http://localhost:3000} volumes: - grafana_data:/var/lib/grafana - ./config/grafana/dashboards:/var/lib/grafana/dashboards:ro - ./config/grafana/provisioning:/etc/grafana/provisioning:ro networks: foxhunt_internal: ipv4_address: 172.20.0.15 depends_on: prometheus: condition: service_healthy healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"] interval: 10s timeout: 5s retries: 5 start_period: 15s deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M # ============================================================================= # API Gateway (Wave 70 - New Service) # ============================================================================= api_gateway: build: context: . dockerfile: services/api_gateway/Dockerfile args: RUST_VERSION: 1.83 container_name: foxhunt-api-gateway restart: unless-stopped environment: # Service configuration API_GATEWAY_HOST: 0.0.0.0 API_GATEWAY_PORT: ${API_GATEWAY_PORT:-50050} METRICS_PORT: ${API_GATEWAY_METRICS_PORT:-9091} # Authentication JWT_SECRET: ${JWT_SECRET} JWT_EXPIRY_SECONDS: ${JWT_EXPIRY_SECONDS:-3600} # Rate limiting RATE_LIMIT_REQUESTS: ${RATE_LIMIT_REQUESTS:-100} RATE_LIMIT_WINDOW_SECS: ${RATE_LIMIT_WINDOW_SECS:-60} # Database and cache DATABASE_URL: postgresql://${POSTGRES_USER:-foxhunt}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-foxhunt} REDIS_URL: redis://redis:6379 # Backend service endpoints TRADING_SERVICE_URL: http://trading_service:50051 BACKTESTING_SERVICE_URL: http://backtesting_service:50052 ML_TRAINING_SERVICE_URL: http://ml_training_service:50053 # Logging RUST_LOG: ${RUST_LOG:-info,api_gateway=debug} RUST_BACKTRACE: ${RUST_BACKTRACE:-1} ports: - "${API_GATEWAY_EXTERNAL_PORT:-50050}:${API_GATEWAY_PORT:-50050}" - "${API_GATEWAY_METRICS_EXTERNAL_PORT:-9091}:${API_GATEWAY_METRICS_PORT:-9091}" networks: - foxhunt_internal - foxhunt_external depends_on: postgres: condition: service_healthy redis: condition: service_healthy vault: condition: service_healthy healthcheck: test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=localhost:${API_GATEWAY_PORT:-50050}"] interval: 10s timeout: 5s retries: 5 start_period: 30s deploy: resources: limits: cpus: '2.0' memory: 1G reservations: cpus: '1.0' memory: 512M # ============================================================================= # Backend Services # ============================================================================= trading_service: build: context: . dockerfile: services/trading_service/Dockerfile args: RUST_VERSION: 1.83 container_name: foxhunt-trading-service restart: unless-stopped environment: # Service configuration TRADING_SERVICE_HOST: 0.0.0.0 TRADING_SERVICE_PORT: ${TRADING_SERVICE_PORT:-50051} METRICS_PORT: ${TRADING_METRICS_PORT:-9092} # Database and cache DATABASE_URL: postgresql://${POSTGRES_USER:-foxhunt}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-foxhunt} REDIS_URL: redis://redis:6379 VAULT_ADDR: http://vault:8200 VAULT_TOKEN: ${VAULT_ROOT_TOKEN} # Logging RUST_LOG: ${RUST_LOG:-info,trading_service=debug} RUST_BACKTRACE: ${RUST_BACKTRACE:-1} networks: foxhunt_internal: ipv4_address: 172.20.0.20 depends_on: postgres: condition: service_healthy redis: condition: service_healthy vault: condition: service_healthy healthcheck: test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=localhost:${TRADING_SERVICE_PORT:-50051}"] interval: 10s timeout: 5s retries: 5 start_period: 30s deploy: resources: limits: cpus: '4.0' memory: 4G reservations: cpus: '2.0' memory: 2G backtesting_service: build: context: . dockerfile: services/backtesting_service/Dockerfile args: RUST_VERSION: 1.83 container_name: foxhunt-backtesting-service restart: unless-stopped environment: # Service configuration BACKTESTING_SERVICE_HOST: 0.0.0.0 BACKTESTING_SERVICE_PORT: ${BACKTESTING_SERVICE_PORT:-50052} METRICS_PORT: ${BACKTESTING_METRICS_PORT:-9093} # Database and cache DATABASE_URL: postgresql://${POSTGRES_USER:-foxhunt}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-foxhunt} REDIS_URL: redis://redis:6379 VAULT_ADDR: http://vault:8200 VAULT_TOKEN: ${VAULT_ROOT_TOKEN} # Logging RUST_LOG: ${RUST_LOG:-info,backtesting_service=debug} RUST_BACKTRACE: ${RUST_BACKTRACE:-1} networks: foxhunt_internal: ipv4_address: 172.20.0.21 depends_on: postgres: condition: service_healthy redis: condition: service_healthy vault: condition: service_healthy healthcheck: test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=localhost:${BACKTESTING_SERVICE_PORT:-50052}"] interval: 10s timeout: 5s retries: 5 start_period: 30s deploy: resources: limits: cpus: '2.0' memory: 2G reservations: cpus: '1.0' memory: 1G ml_training_service: build: context: . dockerfile: services/ml_training_service/Dockerfile args: RUST_VERSION: 1.83 container_name: foxhunt-ml-training-service restart: unless-stopped environment: # Service configuration ML_TRAINING_SERVICE_HOST: 0.0.0.0 ML_TRAINING_SERVICE_PORT: ${ML_TRAINING_SERVICE_PORT:-50053} METRICS_PORT: ${ML_TRAINING_METRICS_PORT:-9094} # Database and cache DATABASE_URL: postgresql://${POSTGRES_USER:-foxhunt}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-foxhunt} REDIS_URL: redis://redis:6379 VAULT_ADDR: http://vault:8200 VAULT_TOKEN: ${VAULT_ROOT_TOKEN} # S3 configuration for model storage AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} AWS_REGION: ${AWS_REGION:-us-east-1} S3_MODEL_BUCKET: ${S3_MODEL_BUCKET:-foxhunt-models} # Logging RUST_LOG: ${RUST_LOG:-info,ml_training_service=debug} RUST_BACKTRACE: ${RUST_BACKTRACE:-1} networks: foxhunt_internal: ipv4_address: 172.20.0.22 depends_on: postgres: condition: service_healthy redis: condition: service_healthy vault: condition: service_healthy healthcheck: test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=localhost:${ML_TRAINING_SERVICE_PORT:-50053}"] interval: 10s timeout: 5s retries: 5 start_period: 30s deploy: resources: limits: cpus: '4.0' memory: 8G reservations: cpus: '2.0' memory: 4G # ============================================================================= # TLI (Terminal Interface Client) - Optional for debugging # ============================================================================= tli: build: context: . dockerfile: tli/Dockerfile args: RUST_VERSION: 1.83 container_name: foxhunt-tli stdin_open: true tty: true environment: # API Gateway connection API_GATEWAY_URL: http://api_gateway:${API_GATEWAY_PORT:-50050} # Logging RUST_LOG: ${RUST_LOG:-info,tli=debug} RUST_BACKTRACE: ${RUST_BACKTRACE:-1} networks: - foxhunt_internal depends_on: api_gateway: condition: service_healthy # No restart policy - TLI is interactive profiles: - debug