version: '3.8' # ============================================================================= # Production Docker Compose Configuration with Docker Secrets # ============================================================================= # This file demonstrates secure secrets management using Docker Swarm secrets. # # IMPORTANT: This configuration requires Docker Swarm mode: # docker swarm init # docker stack deploy -c docker-compose.prod.yml foxhunt # # For Kubernetes deployment, see docs/KUBERNETES_DEPLOYMENT.md # ============================================================================= secrets: # JWT Authentication jwt_secret: external: true name: foxhunt_jwt_secret # Database Credentials postgres_password: external: true name: foxhunt_postgres_password postgres_user: external: true name: foxhunt_postgres_user # Redis Password (if auth enabled) redis_password: external: true name: foxhunt_redis_password # Vault Token vault_token: external: true name: foxhunt_vault_token # InfluxDB Credentials influxdb_admin_token: external: true name: foxhunt_influxdb_token # AWS Credentials aws_access_key_id: external: true name: foxhunt_aws_access_key_id aws_secret_access_key: external: true name: foxhunt_aws_secret_access_key # Benzinga API Key (for backtesting) benzinga_api_key: external: true name: foxhunt_benzinga_api_key # TLS Certificates tls_cert: external: true name: foxhunt_tls_cert tls_key: external: true name: foxhunt_tls_key tls_ca: external: true name: foxhunt_tls_ca services: # =========================================================================== # Infrastructure Services # =========================================================================== postgres: image: timescale/timescaledb:latest-pg16 secrets: - postgres_user - postgres_password environment: POSTGRES_DB: foxhunt POSTGRES_USER_FILE: /run/secrets/postgres_user POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password # Production PostgreSQL tuning POSTGRES_MAX_CONNECTIONS: 500 POSTGRES_SHARED_BUFFERS: 4GB POSTGRES_EFFECTIVE_CACHE_SIZE: 12GB POSTGRES_WORK_MEM: 16MB POSTGRES_MAINTENANCE_WORK_MEM: 1GB # WAL settings for performance POSTGRES_WAL_BUFFERS: 16MB POSTGRES_CHECKPOINT_COMPLETION_TARGET: 0.9 POSTGRES_MAX_WAL_SIZE: 4GB POSTGRES_MIN_WAL_SIZE: 1GB # Async commit for HFT performance (Wave 131 optimization) POSTGRES_SYNCHRONOUS_COMMIT: "off" ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $$(cat /run/secrets/postgres_user)"] interval: 10s timeout: 5s retries: 5 networks: - foxhunt-network deploy: mode: replicated replicas: 1 placement: constraints: - node.role == manager resources: limits: cpus: '4' memory: 16G reservations: cpus: '2' memory: 8G restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 120s redis: image: redis:7-alpine secrets: - redis_password command: > sh -c "redis-server --requirepass $$(cat /run/secrets/redis_password) --maxmemory 2gb --maxmemory-policy allkeys-lru --save 900 1 --save 300 10 --save 60 10000 --appendonly yes --appendfsync everysec" ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "sh", "-c", "redis-cli -a $$(cat /run/secrets/redis_password) ping"] interval: 10s timeout: 5s retries: 5 networks: - foxhunt-network deploy: mode: replicated replicas: 1 resources: limits: cpus: '2' memory: 4G reservations: cpus: '1' memory: 2G restart_policy: condition: on-failure influxdb: image: influxdb:2.7-alpine secrets: - influxdb_admin_token environment: DOCKER_INFLUXDB_INIT_MODE: setup DOCKER_INFLUXDB_INIT_USERNAME: foxhunt DOCKER_INFLUXDB_INIT_PASSWORD_FILE: /run/secrets/influxdb_admin_token DOCKER_INFLUXDB_INIT_ORG: foxhunt DOCKER_INFLUXDB_INIT_BUCKET: trading_metrics DOCKER_INFLUXDB_INIT_RETENTION: 90d ports: - "8086:8086" volumes: - influxdb_data:/var/lib/influxdb2 healthcheck: test: ["CMD", "influx", "ping"] interval: 30s timeout: 10s retries: 5 networks: - foxhunt-network deploy: mode: replicated replicas: 1 resources: limits: cpus: '2' memory: 4G reservations: cpus: '1' memory: 2G vault: image: hashicorp/vault:1.15 secrets: - vault_token environment: VAULT_ADDR: http://0.0.0.0:8200 ports: - "8200:8200" volumes: - vault_data:/vault/data - ./config/vault:/vault/config:ro cap_add: - IPC_LOCK command: vault server -config=/vault/config/vault.hcl healthcheck: test: ["CMD", "vault", "status"] interval: 30s timeout: 10s retries: 5 networks: - foxhunt-network deploy: mode: replicated replicas: 1 placement: constraints: - node.role == manager prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - prometheus_data:/prometheus - ./config/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./config/prometheus/rules:/etc/prometheus/rules:ro command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention.time=90d' - '--web.enable-lifecycle' - '--query.max-concurrency=100' healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"] interval: 30s timeout: 10s retries: 5 networks: - foxhunt-network deploy: mode: replicated replicas: 1 resources: limits: cpus: '2' memory: 8G reservations: cpus: '1' memory: 4G grafana: image: grafana/grafana:latest secrets: - source: postgres_password target: grafana_admin_password ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana - ./config/grafana/dashboards:/var/lib/grafana/dashboards:ro - ./config/grafana/provisioning:/etc/grafana/provisioning:ro environment: - GF_SECURITY_ADMIN_PASSWORD__FILE=/run/secrets/grafana_admin_password - GF_USERS_ALLOW_SIGN_UP=false - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/var/lib/grafana/dashboards/hft-trading-performance.json - GF_SERVER_ROOT_URL=https://grafana.foxhunt.example.com - GF_SECURITY_COOKIE_SECURE=true - GF_SECURITY_STRICT_TRANSPORT_SECURITY=true depends_on: - prometheus healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1"] interval: 30s timeout: 10s retries: 5 networks: - foxhunt-network deploy: mode: replicated replicas: 1 # =========================================================================== # Application Services # =========================================================================== api_gateway: image: foxhunt/api-gateway:${VERSION:-latest} secrets: - jwt_secret - postgres_password - postgres_user - redis_password - vault_token - tls_cert - tls_key - tls_ca environment: - GATEWAY_BIND_ADDR=0.0.0.0:50050 - DATABASE_URL_FILE=/run/secrets/postgres_password - REDIS_PASSWORD_FILE=/run/secrets/redis_password - VAULT_ADDR=http://vault:8200 - VAULT_TOKEN_FILE=/run/secrets/vault_token - TRADING_SERVICE_URL=http://trading_service:50051 - BACKTESTING_SERVICE_URL=http://backtesting_service:50053 - ML_TRAINING_SERVICE_URL=http://ml_training_service:50053 - JWT_SECRET_FILE=/run/secrets/jwt_secret - JWT_ISSUER=foxhunt-api-gateway - JWT_AUDIENCE=foxhunt-services - RATE_LIMIT_RPS=1000 - ENABLE_AUDIT_LOGGING=true - ENABLE_TLS=true - TLS_CERT_FILE=/run/secrets/tls_cert - TLS_KEY_FILE=/run/secrets/tls_key - TLS_CA_FILE=/run/secrets/tls_ca - RUST_LOG=info - RUST_BACKTRACE=0 ports: - "50051:50050" - "9091:9091" depends_on: - postgres - redis - vault - trading_service - backtesting_service healthcheck: test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=localhost:50050"] interval: 10s timeout: 5s start_period: 30s retries: 3 networks: - foxhunt-network deploy: mode: replicated replicas: 3 update_config: parallelism: 1 delay: 10s order: start-first rollback_config: parallelism: 1 delay: 10s resources: limits: cpus: '2' memory: 2G reservations: cpus: '1' memory: 1G restart_policy: condition: on-failure delay: 5s max_attempts: 3 trading_service: image: foxhunt/trading-service:${VERSION:-latest} secrets: - postgres_password - postgres_user - redis_password - vault_token - tls_cert - tls_key - tls_ca environment: - DATABASE_URL_FILE=/run/secrets/postgres_password - REDIS_PASSWORD_FILE=/run/secrets/redis_password - VAULT_ADDR=http://vault:8200 - VAULT_TOKEN_FILE=/run/secrets/vault_token - ENABLE_TLS=true - TLS_CERT_FILE=/run/secrets/tls_cert - TLS_KEY_FILE=/run/secrets/tls_key - TLS_CA_FILE=/run/secrets/tls_ca - RUST_LOG=info - RUST_BACKTRACE=0 ports: - "50052:50051" - "9092:9092" depends_on: - postgres - redis - vault healthcheck: test: ["CMD", "/usr/local/bin/grpc_health_probe", "-addr=localhost:50051"] interval: 10s timeout: 5s start_period: 30s retries: 3 networks: - foxhunt-network deploy: mode: replicated replicas: 2 update_config: parallelism: 1 delay: 10s resources: limits: cpus: '4' memory: 4G reservations: cpus: '2' memory: 2G restart_policy: condition: on-failure backtesting_service: image: foxhunt/backtesting-service:${VERSION:-latest} secrets: - postgres_password - postgres_user - redis_password - vault_token - benzinga_api_key - aws_access_key_id - aws_secret_access_key - tls_cert - tls_key - tls_ca environment: - DATABASE_URL_FILE=/run/secrets/postgres_password - REDIS_PASSWORD_FILE=/run/secrets/redis_password - VAULT_ADDR=http://vault:8200 - VAULT_TOKEN_FILE=/run/secrets/vault_token - BENZINGA_API_KEY_FILE=/run/secrets/benzinga_api_key - AWS_ACCESS_KEY_ID_FILE=/run/secrets/aws_access_key_id - AWS_SECRET_ACCESS_KEY_FILE=/run/secrets/aws_secret_access_key - ENABLE_TLS=true - TLS_CERT_FILE=/run/secrets/tls_cert - TLS_KEY_FILE=/run/secrets/tls_key - TLS_CA_FILE=/run/secrets/tls_ca - RUST_LOG=info - RUST_BACKTRACE=0 ports: - "50053:50053" - "9093:9093" - "8083:8082" depends_on: - postgres - redis - vault healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8082/health"] interval: 10s timeout: 5s start_period: 30s retries: 3 networks: - foxhunt-network deploy: mode: replicated replicas: 1 resources: limits: cpus: '4' memory: 8G reservations: cpus: '2' memory: 4G ml_training_service: image: foxhunt/ml-training-service:${VERSION:-latest} secrets: - postgres_password - postgres_user - redis_password - vault_token - aws_access_key_id - aws_secret_access_key - tls_cert - tls_key - tls_ca environment: - DATABASE_URL_FILE=/run/secrets/postgres_password - REDIS_PASSWORD_FILE=/run/secrets/redis_password - VAULT_ADDR=http://vault:8200 - VAULT_TOKEN_FILE=/run/secrets/vault_token - AWS_ACCESS_KEY_ID_FILE=/run/secrets/aws_access_key_id - AWS_SECRET_ACCESS_KEY_FILE=/run/secrets/aws_secret_access_key - ENABLE_TLS=true - TLS_CERT_FILE=/run/secrets/tls_cert - TLS_KEY_FILE=/run/secrets/tls_key - TLS_CA_FILE=/run/secrets/tls_ca - NVIDIA_VISIBLE_DEVICES=all - NVIDIA_DRIVER_CAPABILITIES=compute,utility - CUDA_VISIBLE_DEVICES=0 - RUST_LOG=info - RUST_BACKTRACE=0 ports: - "50054:50053" - "9094:9094" - "8095:8080" volumes: - ml_models:/tmp/foxhunt/models - ml_checkpoints:/tmp/foxhunt/checkpoints depends_on: - postgres - redis - vault healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 10s timeout: 5s start_period: 60s retries: 3 networks: - foxhunt-network deploy: mode: replicated replicas: 1 placement: constraints: - node.labels.gpu == true resources: limits: cpus: '8' memory: 16G reservations: cpus: '4' memory: 8G generic_resources: - discrete_resource_spec: kind: 'NVIDIA-GPU' value: 1 volumes: postgres_data: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/postgres redis_data: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/redis influxdb_data: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/influxdb vault_data: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/vault prometheus_data: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/prometheus grafana_data: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/grafana ml_models: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/models ml_checkpoints: driver: local driver_opts: type: none o: bind device: /mnt/data/foxhunt/checkpoints networks: foxhunt-network: driver: overlay attachable: true ipam: config: - subnet: 10.10.0.0/16