# ============================================================================== # Enterprise Production Multi-Container Orchestration Specification # Privacy-Preserving Cross-Bank Fraud Detection Consortium (CFI) # Usage: # Quick Start: docker compose up -d --build # With Observability: docker compose --profile monitoring up -d --build # ============================================================================== services: # ── 1. Enterprise Security Gateway & Reverse Proxy ────────────────────────── gateway: image: nginx:1.27-alpine container_name: cfi-gateway restart: unless-stopped ports: - "${CFI_PORT_HTTP:-80}:80" - "${CFI_PORT_HTTPS:-443}:443" volumes: - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro depends_on: backend: condition: service_healthy frontend: condition: service_healthy networks: - cfi-network healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1/gateway-health"] interval: 10s timeout: 3s retries: 3 # ── 2. Frontend Web Container (React 19 SPA) ──────────────────────────────── frontend: build: context: . dockerfile: docker/Dockerfile.frontend image: cfi-intelligence/frontend:latest container_name: cfi-frontend restart: unless-stopped networks: - cfi-network healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1/health"] interval: 10s timeout: 3s retries: 3 # ── 3. Backend API & Federated ML Engine ──────────────────────────────────── backend: build: context: . dockerfile: docker/Dockerfile.backend image: cfi-intelligence/backend:latest container_name: cfi-api-server restart: unless-stopped ports: - "${CFI_PORT_GRPC:-50051}:50051" environment: - APP_ENV=production - LOG_LEVEL=${LOG_LEVEL:-INFO} - DATABASE_TYPE=postgres - POSTGRES_HOST=postgres - POSTGRES_PORT=5432 - POSTGRES_USER=${POSTGRES_USER:-cfi_admin} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-cfi_secure_pass_2026_change_in_production} - POSTGRES_DB=${POSTGRES_DB:-cfi_fraud_db} - DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER:-cfi_admin}:${POSTGRES_PASSWORD:-cfi_secure_pass_2026_change_in_production}@postgres:5432/${POSTGRES_DB:-cfi_fraud_db} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-cfi_redis_secure_pass_2026_change_in_production} - REDIS_URL=redis://:${REDIS_PASSWORD:-cfi_redis_secure_pass_2026_change_in_production}@redis:6379/0 - SECRET_KEY=${SECRET_KEY:-cfi_super_secret_jwt_key_2026_enterprise_floor} - CONSORTIUM_HMAC_SALT=${CONSORTIUM_HMAC_SALT:-cfi_salt_consortium_hmac_sha256_floor_token_2026} - CFI_REGULATORY_ENVELOPE_SECRET=${CFI_REGULATORY_ENVELOPE_SECRET:-cfi_regulatory_envelope_hmac_secret_2026_enterprise} - CFI_STORAGE_DIR=/app/storage - TELEMETRY_ENABLED=true - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 - KAFKA_BOOTSTRAP_SERVERS=${KAFKA_BOOTSTRAP_SERVERS:-kafka:9092} - KAFKA_GROUP_ID=${KAFKA_GROUP_ID:-cfi-fraud-detection-group} - KAFKA_TRANSACTION_TOPIC=${KAFKA_TRANSACTION_TOPIC:-org.cfi.finint.transactions.v1} - KAFKA_ALERT_TOPIC=${KAFKA_ALERT_TOPIC:-org.cfi.finint.alerts.v1} - KAFKA_DLQ_TOPIC=${KAFKA_DLQ_TOPIC:-org.cfi.finint.dlq.v1} - KAFKA_ENABLED=${KAFKA_ENABLED:-true} depends_on: postgres: condition: service_healthy redis: condition: service_healthy volumes: - storage-data:/app/storage - ./backend/storage/datasets:/app/storage/datasets:ro - ./backend/storage/datasets:/app/backend/storage/datasets:ro - logs-data:/app/logs networks: - cfi-network healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"] interval: 10s timeout: 3s start_period: 20s retries: 3 # ── 4. PostgreSQL 16 Enterprise Database ──────────────────────────────────── postgres: image: postgres:16-alpine container_name: cfi-postgres restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-cfi_admin} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-cfi_secure_pass_2026_change_in_production} POSTGRES_DB: ${POSTGRES_DB:-cfi_fraud_db} ports: - "${CFI_PORT_PG:-5432}:5432" volumes: - postgres-data:/var/lib/postgresql/data - ./docker/postgres/01-init.sql:/docker-entrypoint-initdb.d/01-init.sql:ro networks: - cfi-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-cfi_admin} -d ${POSTGRES_DB:-cfi_fraud_db}"] interval: 5s timeout: 3s retries: 5 # ── 5. Redis 7.2 Cache & Message Broker ───────────────────────────────────── redis: image: redis:7.2-alpine container_name: cfi-redis restart: unless-stopped command: > redis-server --requirepass ${REDIS_PASSWORD:-cfi_redis_secure_pass_2026_change_in_production} --appendonly yes --maxmemory 512mb --maxmemory-policy volatile-lru ports: - "${CFI_PORT_REDIS:-6379}:6379" volumes: - redis-data:/data networks: - cfi-network healthcheck: test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "${REDIS_PASSWORD:-cfi_redis_secure_pass_2026_change_in_production}", "ping"] interval: 5s timeout: 3s retries: 3 # ── 6. (Optional) OpenTelemetry Collector ─────────────────────────────────── otel-collector: image: otel/opentelemetry-collector-contrib:0.95.0 container_name: cfi-otel-collector profiles: ["monitoring"] restart: unless-stopped command: ["--config=/etc/otelcol/config.yaml"] volumes: - ./docker/otel/otel-collector-config.yaml:/etc/otelcol/config.yaml ports: - "4317:4317" - "4318:4318" - "8889:8889" networks: - cfi-network # ── 7. (Optional) Prometheus Metrics Engine ───────────────────────────────── prometheus: image: prom/prometheus:v2.50.1 container_name: cfi-prometheus profiles: ["monitoring"] restart: unless-stopped volumes: - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus ports: - "9090:9090" networks: - cfi-network # ── 8. (Optional) Grafana Operations Dashboard ────────────────────────────── grafana: image: grafana/grafana-oss:10.3.3 container_name: cfi-grafana profiles: ["monitoring"] restart: unless-stopped environment: - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER:-admin} - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin} - GF_USERS_ALLOW_SIGN_UP=false volumes: - ./docker/grafana/provisioning:/etc/grafana/provisioning - grafana-data:/var/lib/grafana ports: - "${CFI_PORT_GRAFANA:-3001}:3000" depends_on: - prometheus networks: - cfi-network # ── 9. (Optional) HashiCorp Vault KMS / PKI / Transit Engine ──────────────── vault: image: hashicorp/vault:1.16.2 container_name: cfi-vault profiles: ["enterprise"] restart: unless-stopped ports: - "${CFI_PORT_VAULT:-8200}:8200" environment: VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_TOKEN:-dev-token} VAULT_DEV_LISTEN_ADDRESS: "0.0.0.0:8200" VAULT_ADDR: "http://0.0.0.0:8200" cap_add: - IPC_LOCK volumes: - vault-data:/vault/file networks: - cfi-network healthcheck: test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8200/v1/sys/health || exit 1"] interval: 10s timeout: 5s retries: 3 # ── 10. (Optional) MinIO S3-Compatible Object Store ───────────────────────── minio: image: minio/minio:RELEASE.2024-03-05T04-48-44Z container_name: cfi-minio profiles: ["storage"] restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-cfi_minio_admin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-cfi_minio_secret_pass_2026} ports: - "${CFI_PORT_MINIO:-9000}:9000" - "${CFI_PORT_MINIO_CONSOLE:-9001}:9001" volumes: - minio-data:/data networks: - cfi-network healthcheck: test: ["CMD-SHELL", "curl -f http://127.0.0.1:9000/minio/health/live || exit 1"] interval: 10s timeout: 3s retries: 3 # ── 11. (Optional) MLflow Experiment & Artifact Tracking ──────────────────── mlflow: image: ghcr.io/mlflow/mlflow:v2.11.1 container_name: cfi-mlflow profiles: ["ml"] restart: unless-stopped command: mlflow server --host 0.0.0.0 --port 5000 --backend-store-uri sqlite:////mlflow/mlflow.db --default-artifact-root /mlflow/artifacts ports: - "${CFI_PORT_MLFLOW:-5000}:5000" volumes: - mlflow-data:/mlflow networks: - cfi-network healthcheck: test: ["CMD-SHELL", "curl -f http://127.0.0.1:5000/health || exit 1"] interval: 10s timeout: 3s retries: 3 # ── 12. Apache Kafka 3.7 Event Streaming Bus (KRaft Mode) ─────────────────── kafka: image: apache/kafka:3.7.0 container_name: cfi-kafka restart: unless-stopped ports: - "${CFI_PORT_KAFKA:-9092}:9092" environment: KAFKA_NODE_ID: 1 KAFKA_PROCESS_ROLES: broker,controller KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 KAFKA_NUM_PARTITIONS: 3 volumes: - kafka-data:/var/lib/kafka/data networks: - cfi-network healthcheck: test: ["CMD-SHELL", "/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list || exit 1"] interval: 10s timeout: 5s retries: 5 networks: cfi-network: driver: bridge volumes: postgres-data: redis-data: storage-data: logs-data: prometheus-data: grafana-data: minio-data: mlflow-data: kafka-data: vault-data: