# Microservices Architecture
# API Gateway + Multiple Services + Service Mesh + Message Queue
# Production-ready microservices deployment

services:
  # API Gateway (Kong)
  api-gateway:
    image: kong:3.5-alpine
    container_name: api-gateway
    restart: unless-stopped
    ports:
      - "8000:8000"  # HTTP
      - "8443:8443"  # HTTPS
      - "8001:8001"  # Admin API
    environment:
      - KONG_DATABASE=postgres
      - KONG_PG_HOST=gateway-db
      - KONG_PG_USER=${KONG_DB_USER}
      - KONG_PG_PASSWORD=${KONG_DB_PASSWORD}
      - KONG_PG_DATABASE=${KONG_DB_NAME}
      - KONG_PROXY_ACCESS_LOG=/dev/stdout
      - KONG_ADMIN_ACCESS_LOG=/dev/stdout
      - KONG_PROXY_ERROR_LOG=/dev/stderr
      - KONG_ADMIN_ERROR_LOG=/dev/stderr
      - KONG_ADMIN_LISTEN=0.0.0.0:8001
    networks:
      - public
      - backend
    depends_on:
      gateway-db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "kong", "health"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M

  # Kong Database
  gateway-db:
    image: postgres:16-alpine
    container_name: gateway-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=${KONG_DB_USER}
      - POSTGRES_PASSWORD=${KONG_DB_PASSWORD}
      - POSTGRES_DB=${KONG_DB_NAME}
    volumes:
      - kong-data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${KONG_DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

  # User Service
  user-service:
    image: user-service:1.0.0
    container_name: user-service
    restart: unless-stopped
    environment:
      - SERVICE_PORT=3001
      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@services-db:5432/users
      - REDIS_URL=redis://redis:6379
      - RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
    networks:
      - backend
      - data
    depends_on:
      services-db:
        condition: service_healthy
      redis:
        condition: service_healthy
      rabbitmq:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # Product Service
  product-service:
    image: product-service:1.0.0
    container_name: product-service
    restart: unless-stopped
    environment:
      - SERVICE_PORT=3002
      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@services-db:5432/products
      - REDIS_URL=redis://redis:6379
      - RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
    networks:
      - backend
      - data
    depends_on:
      services-db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3002/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # Order Service
  order-service:
    image: order-service:1.0.0
    container_name: order-service
    restart: unless-stopped
    environment:
      - SERVICE_PORT=3003
      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@services-db:5432/orders
      - REDIS_URL=redis://redis:6379
      - RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
      - USER_SERVICE_URL=http://user-service:3001
      - PRODUCT_SERVICE_URL=http://product-service:3002
    networks:
      - backend
      - data
    depends_on:
      services-db:
        condition: service_healthy
      user-service:
        condition: service_healthy
      product-service:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3003/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # Shared Database for Services
  services-db:
    image: postgres:16-alpine
    container_name: services-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_MULTIPLE_DATABASES=users,products,orders
    volumes:
      - services-data:/var/lib/postgresql/data
      - ./database/init-multiple-dbs.sh:/docker-entrypoint-initdb.d/init-multiple-dbs.sh:ro
    networks:
      - data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G

  # Redis for Caching
  redis:
    image: redis:7-alpine
    container_name: services-redis
    restart: unless-stopped
    command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru
    volumes:
      - redis-data:/data
    networks:
      - data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

  # RabbitMQ for Message Queue
  rabbitmq:
    image: rabbitmq:3.12-management-alpine
    container_name: services-rabbitmq
    restart: unless-stopped
    ports:
      - "15672:15672"  # Management UI
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    networks:
      - data
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G

  # Service Discovery (Consul)
  consul:
    image: consul:1.17
    container_name: consul
    restart: unless-stopped
    ports:
      - "8500:8500"  # UI and HTTP API
      - "8600:8600/udp"  # DNS
    command: agent -server -ui -bootstrap-expect=1 -client=0.0.0.0
    volumes:
      - consul-data:/consul/data
    networks:
      - backend
    healthcheck:
      test: ["CMD", "consul", "members"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M

networks:
  public:
    driver: bridge
  backend:
    driver: bridge
  data:
    driver: bridge
    internal: true

volumes:
  kong-data:
  services-data:
  redis-data:
  rabbitmq-data:
  consul-data:
