# ============================================================================= # GoodGo Platform - Local Development Environment # ============================================================================= # # Prerequisites: # 1. Copy env.local.example to .env.local and configure values # 2. Ensure Docker and Docker Compose are installed # 3. Get Neon PostgreSQL URL from https://console.neon.tech # # Start: docker-compose up -d # Stop: docker-compose down # Logs: docker-compose logs -f [service-name] # # Access Points: # - Traefik Dashboard: http://localhost:8080 # - IAM Service: http://localhost/api/v1/auth (backward compatible) # - IAM Service: http://localhost/api/v1/identity, /api/v1/access, /api/v1/governance # - Web Admin: http://admin.localhost # - Web Client: http://localhost # # ============================================================================= services: # =========================================================================== # SHARED INFRASTRUCTURE # =========================================================================== # PostgreSQL 16 - Shared Database Server postgres: image: postgres:16-alpine container_name: postgres-local environment: - POSTGRES_USER=goodgo - POSTGRES_PASSWORD=goodgo-local-2024 - POSTGRES_DB=postgres ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh:ro networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U goodgo"] interval: 10s timeout: 5s retries: 5 start_period: 10s # Redis 7 - Cache & SignalR Backplane redis: image: redis:7-alpine container_name: redis-local command: redis-server --requirepass goodgo-redis-local ports: - "6379:6379" volumes: - redis_data:/data networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "-a", "goodgo-redis-local", "ping"] interval: 10s timeout: 5s retries: 5 # Redis Exporter - Prometheus metrics for Redis (DEVOPS-W-01) redis-exporter: image: oliver006/redis_exporter:latest container_name: redis-exporter-local environment: REDIS_ADDR: "redis://redis:6379" REDIS_PASSWORD: "goodgo-redis-local" ports: - "9121:9121" networks: - microservices-network depends_on: redis: condition: service_healthy restart: unless-stopped # MinIO - Object Storage (S3-compatible) minio: image: minio/minio:latest container_name: minio-local command: server /data --console-address ":9001" environment: - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin123 ports: - "9000:9000" # API - "9001:9001" # Console volumes: - minio_data:/data networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 10s timeout: 5s retries: 5 start_period: 10s # RabbitMQ 3 - Message Broker (for Ads services) rabbitmq: image: rabbitmq:3-management-alpine container_name: rabbitmq-local environment: - RABBITMQ_DEFAULT_USER=guest - RABBITMQ_DEFAULT_PASS=goodgo-rabbitmq-local ports: - "5672:5672" # AMQP - "15672:15672" # Management UI volumes: - rabbitmq_data:/var/lib/rabbitmq networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 15s timeout: 10s retries: 5 start_period: 30s # Traefik - API Gateway and Reverse Proxy traefik: image: traefik:v3.3 container_name: traefik-local command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.network=goodgo-network" - "--providers.file.directory=/etc/traefik/dynamic" - "--providers.file.watch=true" - "--entrypoints.web.address=:80" - "--log.level=${LOG_LEVEL:-INFO}" - "--accesslog=true" ports: - "80:80" # HTTP - "8080:8080" # Dashboard volumes: # EN: Use actual Docker Desktop socket path (not symlink) # VI: Sử dụng đường dẫn socket thực của Docker Desktop (không phải symlink) - /var/run/docker.sock:/var/run/docker.sock:ro - ../../infra/traefik:/etc/traefik:ro networks: - microservices-network restart: unless-stopped labels: - "traefik.enable=true" - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.localhost`)" - "traefik.http.routers.traefik-dashboard.entrypoints=web" - "traefik.http.routers.traefik-dashboard.service=api@internal" # =========================================================================== # BACKEND SERVICES # =========================================================================== # Storage Service .NET - File Storage Management storage-service: build: context: ../../services/storage-service-net dockerfile: Dockerfile image: goodgo/storage-service-net:latest container_name: storage-service-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 - ConnectionStrings__DefaultConnection=${STORAGE_DATABASE_URL} - Storage__Provider=minio - Storage__DefaultBucket=goodgo - Storage__MinIO__Endpoint=${MINIO_ENDPOINT} - Storage__MinIO__AccessKey=${MINIO_ACCESS_KEY} - Storage__MinIO__SecretKey=${MINIO_SECRET_KEY} - Storage__MinIO__UseSSL=false - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=storage-service - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} ports: - "5002:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.storage-service.rule=PathPrefix(`/api/v1/files`) || PathPrefix(`/api/v1/quota`)" - "traefik.http.routers.storage-service.entrypoints=web" - "traefik.http.services.storage-service.loadbalancer.server.port=8080" - "traefik.http.services.storage-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.storage-service.loadbalancer.healthcheck.interval=10s" # Membership Service .NET - Membership Management membership-service-net: build: context: ../../services/membership-service-net dockerfile: Dockerfile image: goodgo/membership-service-net:latest container_name: membership-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${MEMBERSHIP_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=membership-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5003:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.membership-service.rule=PathPrefix(`/api/v1/members`) || PathPrefix(`/api/v1/levels`) || PathPrefix(`/api/v1/memberships`) || PathPrefix(`/api/v1/subscriptions`)" - "traefik.http.routers.membership-service.entrypoints=web" - "traefik.http.services.membership-service.loadbalancer.server.port=8080" - "traefik.http.services.membership-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.membership-service.loadbalancer.healthcheck.interval=10s" # Merchant Service .NET - Merchant & Shop Management merchant-service-net: build: context: ../../services/merchant-service-net dockerfile: Dockerfile image: goodgo/merchant-service-net:latest container_name: merchant-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${MERCHANT_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=merchant-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5005:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.merchant-service.rule=PathPrefix(`/api/v1/merchants`) || PathPrefix(`/api/v1/shops`)" - "traefik.http.routers.merchant-service.entrypoints=web" - "traefik.http.services.merchant-service.loadbalancer.server.port=8080" - "traefik.http.services.merchant-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.merchant-service.loadbalancer.healthcheck.interval=10s" # IAM Service .NET - Identity and Access Management (Duende IdentityServer) iam-service-net: build: context: ../../services/iam-service-net dockerfile: Dockerfile image: goodgo/iam-service-net:latest container_name: iam-service-net-local env_file: - .env environment: - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Development} - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${IAM_DATABASE_URL} # EN: Redis Cache (external) # VI: Cache Redis (bên ngoài) - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} - Redis__Database=${REDIS_DATABASE} # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Secret=${JWT_SECRET} - Jwt__Issuer=${JWT_ISSUER} - Jwt__Audience=${JWT_AUDIENCE} - Jwt__AccessTokenExpiryMinutes=${JWT_ACCESS_TOKEN_EXPIRY_MINUTES} - Jwt__RefreshTokenExpiryDays=${JWT_REFRESH_TOKEN_EXPIRY_DAYS} # EN: Features # VI: Tính năng - Features__SwaggerEnabled=${FEATURE_SWAGGER_ENABLED} - Features__DetailedErrors=${FEATURE_DETAILED_ERRORS} # EN: IdentityServer - Fixed issuer for inter-service communication # VI: IdentityServer - Issuer cố định cho giao tiếp giữa các service - IdentityServer__IssuerUri=http://iam-service ports: - "5001:8080" depends_on: postgres: condition: service_healthy redis: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 60s labels: - "traefik.enable=true" - "traefik.http.routers.iam-service-net.rule=PathPrefix(`/api/v1/iam`) || PathPrefix(`/api/v1/auth`) || PathPrefix(`/api/v1/users`) || PathPrefix(`/api/v1/roles`)" - "traefik.http.routers.iam-service-net.entrypoints=web" - "traefik.http.services.iam-service-net.loadbalancer.server.port=8080" - "traefik.http.services.iam-service-net.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.iam-service-net.loadbalancer.healthcheck.interval=10s" # Wallet Service .NET - Wallet & PPoint Management wallet-service-net: build: context: ../../services/wallet-service-net dockerfile: Dockerfile image: goodgo/wallet-service-net:latest container_name: wallet-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${WALLET_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=wallet-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5004:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.wallet-service.rule=PathPrefix(`/api/v1/wallets`) || PathPrefix(`/api/v1/points`) || PathPrefix(`/api/v1/admin/wallets`) || PathPrefix(`/api/v1/admin/points`)" - "traefik.http.routers.wallet-service.entrypoints=web" - "traefik.http.services.wallet-service.loadbalancer.server.port=8080" - "traefik.http.services.wallet-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.wallet-service.loadbalancer.healthcheck.interval=10s" # Chat Service .NET - Real-time Chat with SignalR chat-service-net: build: context: ../../services/chat-service-net dockerfile: Dockerfile image: goodgo/chat-service-net:latest container_name: chat-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${CHAT_DATABASE_URL} # EN: Redis for SignalR Backplane # VI: Redis cho SignalR Backplane - ConnectionStrings__Redis=${REDIS_CONNECTION_STRING} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=chat-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: SignalR Configuration # VI: Cấu hình SignalR - SignalR__EnableMessagePack=true - SignalR__StatefulReconnectBufferSize=32768 ports: - "5010:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" # EN: HTTP API routes # VI: Routes cho HTTP API - "traefik.http.routers.chat-service.rule=PathPrefix(`/api/v1/conversations`) || PathPrefix(`/api/v1/messages`) || PathPrefix(`/api/v1/chat`)" - "traefik.http.routers.chat-service.entrypoints=web" - "traefik.http.services.chat-service.loadbalancer.server.port=8080" - "traefik.http.services.chat-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.chat-service.loadbalancer.healthcheck.interval=10s" # EN: SignalR Hub route with sticky sessions # VI: Route cho SignalR Hub với sticky sessions - "traefik.http.routers.chat-hub.rule=PathPrefix(`/hubs/chat`)" - "traefik.http.routers.chat-hub.entrypoints=web" - "traefik.http.routers.chat-hub.service=chat-service" - "traefik.http.services.chat-service.loadbalancer.sticky.cookie=true" - "traefik.http.services.chat-service.loadbalancer.sticky.cookie.name=chat_session" # Social Service .NET - Social Features (Profiles, Posts, Followers) social-service-net: build: context: ../../services/social-service-net dockerfile: Dockerfile image: goodgo/social-service-net:latest container_name: social-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${SOCIAL_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=social-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache # VI: Cache Redis - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} ports: - "5009:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.social-service.rule=PathPrefix(`/api/v1/profiles`) || PathPrefix(`/api/v1/posts`) || PathPrefix(`/api/v1/followers`) || PathPrefix(`/api/v1/social`)" - "traefik.http.routers.social-service.entrypoints=web" - "traefik.http.services.social-service.loadbalancer.server.port=8080" - "traefik.http.services.social-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.social-service.loadbalancer.healthcheck.interval=10s" # Mining Service .NET - Pi Network-style Point Mining mining-service-net: build: context: ../../services/mining-service-net dockerfile: Dockerfile image: goodgo/mining-service-net:latest container_name: mining-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${MINING_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=mining-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache # VI: Cache Redis - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} ports: - "5006:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.mining-service.rule=PathPrefix(`/api/v1/mining`) || PathPrefix(`/api/v1/circles`) || PathPrefix(`/api/v1/referrals`)" - "traefik.http.routers.mining-service.entrypoints=web" - "traefik.http.services.mining-service.loadbalancer.server.port=8080" - "traefik.http.services.mining-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.mining-service.loadbalancer.healthcheck.interval=10s" # EN: SignalR Hub route with sticky sessions # VI: Route cho SignalR Hub với sticky sessions - "traefik.http.routers.mining-hub.rule=PathPrefix(`/hubs/mining`)" - "traefik.http.routers.mining-hub.entrypoints=web" - "traefik.http.routers.mining-hub.service=mining-service" - "traefik.http.services.mining-service.loadbalancer.sticky.cookie=true" - "traefik.http.services.mining-service.loadbalancer.sticky.cookie.name=mining_session" # Mission Service .NET - Gamification (Check-ins, Missions, Tasks) mission-service-net: build: context: ../../services/mission-service-net dockerfile: Dockerfile image: goodgo/mission-service-net:latest container_name: mission-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${MISSION_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=mission-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache # VI: Cache Redis - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} ports: - "5007:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.mission-service.rule=PathPrefix(`/api/v1/checkins`) || PathPrefix(`/api/v1/missions`) || PathPrefix(`/api/v1/admin/missions`) || PathPrefix(`/api/v1/admin/checkins`) || PathPrefix(`/api/v1/admin/tasks`)" - "traefik.http.routers.mission-service.entrypoints=web" - "traefik.http.services.mission-service.loadbalancer.server.port=8080" - "traefik.http.services.mission-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.mission-service.loadbalancer.healthcheck.interval=10s" # Promotion Service .NET - Voucher, Gift Card, Campaign Management promotion-service-net: build: context: ../../services/promotion-service-net dockerfile: Dockerfile image: goodgo/promotion-service-net:latest container_name: promotion-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${PROMOTION_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=promotion-service # EN: Wallet Service Communication # VI: Giao tiếp Wallet Service - WalletService__BaseUrl=http://wallet-service-net:8080 # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5008:8080" depends_on: iam-service-net: condition: service_healthy wallet-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.promotion-service.rule=PathPrefix(`/api/v1/campaigns`) || PathPrefix(`/api/v1/vouchers`) || PathPrefix(`/api/v1/admin/campaigns`) || PathPrefix(`/api/v1/admin/vouchers`)" - "traefik.http.routers.promotion-service.entrypoints=web" - "traefik.http.services.promotion-service.loadbalancer.server.port=8080" - "traefik.http.services.promotion-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.promotion-service.loadbalancer.healthcheck.interval=10s" # =========================================================================== # MULTI-VERTICAL SERVICES - Product, Order, Inventory Management # =========================================================================== # Catalog Service .NET - Polymorphic Product Management catalog-service-net: build: context: ../../services/catalog-service-net dockerfile: Dockerfile image: goodgo/catalog-service-net:latest container_name: catalog-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${CATALOG_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=catalog-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5016:8080" depends_on: iam-service-net: condition: service_healthy merchant-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.catalog-service.rule=PathPrefix(`/api/v1/products`) || PathPrefix(`/api/v1/categories`)" - "traefik.http.routers.catalog-service.entrypoints=web" - "traefik.http.services.catalog-service.loadbalancer.server.port=8080" - "traefik.http.services.catalog-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.catalog-service.loadbalancer.healthcheck.interval=10s" # Order Service .NET - Order Orchestration with Strategy Pattern order-service-net: build: context: ../../services/order-service-net dockerfile: Dockerfile image: goodgo/order-service-net:latest container_name: order-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${ORDER_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=order-service # EN: Service Communication # VI: Giao tiếp Service - CatalogService__BaseUrl=http://catalog-service-net:8080 - InventoryService__BaseUrl=http://inventory-service-net:8080 - WalletService__BaseUrl=http://wallet-service-net:8080 # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis for caching and SignalR backplane # VI: Redis cho caching và SignalR backplane - Redis__ConnectionString=redis:6379,password=goodgo-redis-local ports: - "5017:8080" depends_on: iam-service-net: condition: service_healthy catalog-service-net: condition: service_healthy redis: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.order-service.rule=PathPrefix(`/api/v1/orders`)" - "traefik.http.routers.order-service.entrypoints=web" - "traefik.http.services.order-service.loadbalancer.server.port=8080" - "traefik.http.services.order-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.order-service.loadbalancer.healthcheck.interval=10s" # Inventory Service .NET - Stock Management (Retail + FnB) inventory-service-net: build: context: ../../services/inventory-service-net dockerfile: Dockerfile image: goodgo/inventory-service-net:latest container_name: inventory-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${INVENTORY_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=inventory-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5018:8080" depends_on: iam-service-net: condition: service_healthy catalog-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.inventory-service.rule=PathPrefix(`/api/v1/inventory`) || PathPrefix(`/api/v1/stock`)" - "traefik.http.routers.inventory-service.entrypoints=web" - "traefik.http.services.inventory-service.loadbalancer.server.port=8080" - "traefik.http.services.inventory-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.inventory-service.loadbalancer.healthcheck.interval=10s" # FnB Engine .NET - Table, Session & Kitchen Management fnb-engine-net: build: context: ../../services/fnb-engine-net dockerfile: Dockerfile image: goodgo/fnb-engine-net:latest container_name: fnb-engine-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${FNB_ENGINE_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=fnb-engine # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis for SignalR (Kitchen Display) # VI: Redis cho SignalR (Màn hình bếp) - ConnectionStrings__Redis=${REDIS_CONNECTION_STRING} ports: - "5019:8080" depends_on: iam-service-net: condition: service_healthy merchant-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.fnb-engine.rule=PathPrefix(`/api/v1/tables`) || PathPrefix(`/api/v1/sessions`) || PathPrefix(`/api/v1/kitchen`)" - "traefik.http.routers.fnb-engine.entrypoints=web" - "traefik.http.services.fnb-engine.loadbalancer.server.port=8080" - "traefik.http.services.fnb-engine.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.fnb-engine.loadbalancer.healthcheck.interval=10s" # EN: SignalR Hub route for Kitchen Display # VI: Route cho SignalR Hub màn hình bếp - "traefik.http.routers.fnb-hub.rule=PathPrefix(`/hubs/kitchen`)" - "traefik.http.routers.fnb-hub.entrypoints=web" - "traefik.http.routers.fnb-hub.service=fnb-engine" - "traefik.http.services.fnb-engine.loadbalancer.sticky.cookie=true" - "traefik.http.services.fnb-engine.loadbalancer.sticky.cookie.name=fnb_session" # Booking Service .NET - Appointment Scheduling (Services, Spa, Salon) booking-service-net: build: context: ../../services/booking-service-net dockerfile: Dockerfile image: goodgo/booking-service-net:latest container_name: booking-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${BOOKING_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=booking-service # EN: Service Communication # VI: Giao tiếp Service - CatalogService__BaseUrl=http://catalog-service-net:8080 - MerchantService__BaseUrl=http://merchant-service-net:8080 # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5020:8080" depends_on: iam-service-net: condition: service_healthy catalog-service-net: condition: service_healthy merchant-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.booking-service.rule=PathPrefix(`/api/v1/appointments`) || PathPrefix(`/api/v1/resources`) || PathPrefix(`/api/v1/schedules`)" - "traefik.http.routers.booking-service.entrypoints=web" - "traefik.http.services.booking-service.loadbalancer.server.port=8080" - "traefik.http.services.booking-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.booking-service.loadbalancer.healthcheck.interval=10s" # Ads Manager Service .NET - Campaign & Ad Management ads-manager-service-net: build: context: ../../services/ads-manager-service-net dockerfile: Dockerfile image: goodgo/ads-manager-service-net:latest container_name: ads-manager-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${ADS_MANAGER_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=ads-manager-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache # VI: Cache Redis - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} ports: - "5011:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.ads-manager-service.rule=PathPrefix(`/api/v1/ads-manager`)" - "traefik.http.routers.ads-manager-service.entrypoints=web" - "traefik.http.services.ads-manager-service.loadbalancer.server.port=8080" - "traefik.http.services.ads-manager-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.ads-manager-service.loadbalancer.healthcheck.interval=10s" # Ads Analytics Service .NET - Ad Performance Analytics & Reporting ads-analytics-service-net: build: context: ../../services/ads-analytics-service-net dockerfile: Dockerfile image: goodgo/ads-analytics-service-net:latest container_name: ads-analytics-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${ADS_ANALYTICS_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=ads-analytics-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache # VI: Cache Redis - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} ports: - "5015:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.ads-analytics-service.rule=PathPrefix(`/api/v1/ads-analytics`) || PathPrefix(`/api/v1/admin/ads-analytics`)" - "traefik.http.routers.ads-analytics-service.entrypoints=web" - "traefik.http.services.ads-analytics-service.loadbalancer.server.port=8080" - "traefik.http.services.ads-analytics-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.ads-analytics-service.loadbalancer.healthcheck.interval=10s" # Ads Serving Service .NET - Real-Time Bidding & Ad Serving (< 100ms) ads-serving-service-net: build: context: ../../services/ads-serving-service-net dockerfile: Dockerfile image: goodgo/ads-serving-service-net:latest container_name: ads-serving-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${ADS_SERVING_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=ads-serving-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache (required for RTB) # VI: Cache Redis (bắt buộc cho RTB) - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} # EN: RabbitMQ for event publishing # VI: RabbitMQ để publish sự kiện - RabbitMQ__Host=rabbitmq - RabbitMQ__Port=5672 - RabbitMQ__Username=${RABBITMQ_USERNAME} - RabbitMQ__Password=${RABBITMQ_PASSWORD} ports: - "5012:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" # EN: Public API routes for ad serving # VI: Routes API công khai để serve quảng cáo - "traefik.http.routers.ads-serving-service.rule=PathPrefix(`/api/v1/ads/serve`) || PathPrefix(`/api/v1/ads/events`)" - "traefik.http.routers.ads-serving-service.entrypoints=web" - "traefik.http.services.ads-serving-service.loadbalancer.server.port=8080" - "traefik.http.services.ads-serving-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.ads-serving-service.loadbalancer.healthcheck.interval=10s" # EN: Admin API routes for monitoring # VI: Routes API Admin để giám sát - "traefik.http.routers.ads-serving-admin.rule=PathPrefix(`/api/v1/admin/auctions`) || PathPrefix(`/api/v1/admin/budget`) || PathPrefix(`/api/v1/admin/frequency`)" - "traefik.http.routers.ads-serving-admin.entrypoints=web" - "traefik.http.routers.ads-serving-admin.service=ads-serving-service" # Ads Billing Service .NET - Billing, Invoicing & Payment Management ads-billing-service-net: build: context: ../../services/ads-billing-service-net dockerfile: Dockerfile image: goodgo/ads-billing-service-net:latest container_name: ads-billing-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${ADS_BILLING_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=ads-billing-service # EN: Wallet Service Communication # VI: Giao tiếp Wallet Service - WalletService__BaseUrl=http://wallet-service-net:8080 # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false ports: - "5013:8080" depends_on: iam-service-net: condition: service_healthy wallet-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" # EN: Public API routes for billing, invoices, credit lines # VI: Routes API công khai cho billing, hóa đơn, tín dụng - "traefik.http.routers.ads-billing-service.rule=PathPrefix(`/api/v1/ads-billing/accounts`) || PathPrefix(`/api/v1/ads-billing/invoices`) || PathPrefix(`/api/v1/ads-billing/credit-lines`)" - "traefik.http.routers.ads-billing-service.entrypoints=web" - "traefik.http.services.ads-billing-service.loadbalancer.server.port=8080" - "traefik.http.services.ads-billing-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.ads-billing-service.loadbalancer.healthcheck.interval=10s" # EN: Admin API routes for billing management # VI: Routes API Admin để quản lý billing - "traefik.http.routers.ads-billing-admin.rule=PathPrefix(`/api/v1/admin/ads-billing`)" - "traefik.http.routers.ads-billing-admin.entrypoints=web" - "traefik.http.routers.ads-billing-admin.service=ads-billing-service" # Ads Tracking Service .NET - Pixel Tracking, Conversion Tracking & Attribution ads-tracking-service-net: build: context: ../../services/ads-tracking-service-net dockerfile: Dockerfile image: goodgo/ads-tracking-service-net:latest container_name: ads-tracking-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: Database - Neon PostgreSQL # VI: Cơ sở dữ liệu - Neon PostgreSQL - ConnectionStrings__DefaultConnection=${ADS_TRACKING_DATABASE_URL} # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 - IamService__ServiceName=ads-tracking-service # EN: JWT Configuration # VI: Cấu hình JWT - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false # EN: Redis Cache (for high-volume event buffering) # VI: Cache Redis (cho buffering sự kiện lưu lượng cao) - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} # EN: RabbitMQ for event publishing # VI: RabbitMQ để publish sự kiện - RabbitMQ__Host=rabbitmq - RabbitMQ__Port=5672 - RabbitMQ__Username=${RABBITMQ_USERNAME} - RabbitMQ__Password=${RABBITMQ_PASSWORD} ports: - "5014:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" # EN: Public API routes for pixel tracking (high traffic, no auth) # VI: Routes API công khai cho pixel tracking (lưu lượng cao, không auth) - "traefik.http.routers.ads-tracking-pixels.rule=PathPrefix(`/api/v1/pixels`)" - "traefik.http.routers.ads-tracking-pixels.entrypoints=web" - "traefik.http.services.ads-tracking-service.loadbalancer.server.port=8080" - "traefik.http.services.ads-tracking-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.ads-tracking-service.loadbalancer.healthcheck.interval=10s" # EN: Conversion tracking API routes # VI: Routes API cho conversion tracking - "traefik.http.routers.ads-tracking-conversions.rule=PathPrefix(`/api/v1/conversions`)" - "traefik.http.routers.ads-tracking-conversions.entrypoints=web" - "traefik.http.routers.ads-tracking-conversions.service=ads-tracking-service" # EN: Admin API routes for analytics and attribution # VI: Routes API Admin cho analytics và attribution - "traefik.http.routers.ads-tracking-admin.rule=PathPrefix(`/api/v1/admin/attribution`) || PathPrefix(`/api/v1/admin/tracking-stats`)" - "traefik.http.routers.ads-tracking-admin.entrypoints=web" - "traefik.http.routers.ads-tracking-admin.service=ads-tracking-service" # Marketing Services - Social Media Integrations # EN: Each service gets unique host port to avoid port 5000 conflicts # VI: Moi service duoc cap port host rieng de tranh xung dot port 5000 mkt-facebook-service-net: build: context: ../../services/mkt-facebook-service-net dockerfile: Dockerfile image: goodgo/mkt-facebook-service-net:latest container_name: mkt-facebook-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 - ConnectionStrings__DefaultConnection=${MKT_FACEBOOK_DATABASE_URL} - IamService__BaseUrl=http://iam-service-net:8080 - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} - RabbitMQ__Host=rabbitmq - RabbitMQ__Port=5672 - RabbitMQ__Username=${RABBITMQ_USERNAME} - RabbitMQ__Password=${RABBITMQ_PASSWORD} ports: - "5021:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.mkt-facebook.rule=PathPrefix(`/api/v1/mkt/facebook`)" - "traefik.http.routers.mkt-facebook.entrypoints=web" - "traefik.http.services.mkt-facebook-service.loadbalancer.server.port=8080" - "traefik.http.services.mkt-facebook-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.mkt-facebook-service.loadbalancer.healthcheck.interval=10s" mkt-whatsapp-service-net: build: context: ../../services/mkt-whatsapp-service-net dockerfile: Dockerfile image: goodgo/mkt-whatsapp-service-net:latest container_name: mkt-whatsapp-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 - ConnectionStrings__DefaultConnection=${MKT_WHATSAPP_DATABASE_URL} - IamService__BaseUrl=http://iam-service-net:8080 - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} - RabbitMQ__Host=rabbitmq - RabbitMQ__Port=5672 - RabbitMQ__Username=${RABBITMQ_USERNAME} - RabbitMQ__Password=${RABBITMQ_PASSWORD} ports: - "5022:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.mkt-whatsapp.rule=PathPrefix(`/api/v1/mkt/whatsapp`)" - "traefik.http.routers.mkt-whatsapp.entrypoints=web" - "traefik.http.services.mkt-whatsapp-service.loadbalancer.server.port=8080" - "traefik.http.services.mkt-whatsapp-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.mkt-whatsapp-service.loadbalancer.healthcheck.interval=10s" mkt-x-service-net: build: context: ../../services/mkt-x-service-net dockerfile: Dockerfile image: goodgo/mkt-x-service-net:latest container_name: mkt-x-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 - ConnectionStrings__DefaultConnection=${MKT_X_DATABASE_URL} - IamService__BaseUrl=http://iam-service-net:8080 - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} - RabbitMQ__Host=rabbitmq - RabbitMQ__Port=5672 - RabbitMQ__Username=${RABBITMQ_USERNAME} - RabbitMQ__Password=${RABBITMQ_PASSWORD} ports: - "5023:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.mkt-x.rule=PathPrefix(`/api/v1/mkt/x`)" - "traefik.http.routers.mkt-x.entrypoints=web" - "traefik.http.services.mkt-x-service.loadbalancer.server.port=8080" - "traefik.http.services.mkt-x-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.mkt-x-service.loadbalancer.healthcheck.interval=10s" mkt-zalo-service-net: build: context: ../../services/mkt-zalo-service-net dockerfile: Dockerfile image: goodgo/mkt-zalo-service-net:latest container_name: mkt-zalo-service-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 - ConnectionStrings__DefaultConnection=${MKT_ZALO_DATABASE_URL} - IamService__BaseUrl=http://iam-service-net:8080 - Jwt__Authority=http://iam-service-net:8080 - Jwt__Audience=goodgo-api - Jwt__RequireHttpsMetadata=false - Redis__Host=${REDIS_HOST} - Redis__Port=${REDIS_PORT} - Redis__Password=${REDIS_PASSWORD} - RabbitMQ__Host=rabbitmq - RabbitMQ__Port=5672 - RabbitMQ__Username=${RABBITMQ_USERNAME} - RabbitMQ__Password=${RABBITMQ_PASSWORD} ports: - "5024:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:8080/health/live || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: - "traefik.enable=true" - "traefik.http.routers.mkt-zalo.rule=PathPrefix(`/api/v1/mkt/zalo`)" - "traefik.http.routers.mkt-zalo.entrypoints=web" - "traefik.http.services.mkt-zalo-service.loadbalancer.server.port=8080" - "traefik.http.services.mkt-zalo-service.loadbalancer.healthcheck.path=/health/live" - "traefik.http.services.mkt-zalo-service.loadbalancer.healthcheck.interval=10s" # Jaeger - Distributed Tracing # jaeger: # image: jaegertracing/all-in-one:1.47 # container_name: jaeger-local # ports: # - "16686:16686" # UI # - "14268:14268" # Collector # environment: # - COLLECTOR_OTLP_ENABLED=true # networks: # - microservices-network # restart: unless-stopped # Alertmanager - Alert Routing & Notification Delivery alertmanager: image: prom/alertmanager:v0.27.0 container_name: alertmanager-local command: - '--config.file=/etc/alertmanager/alertmanager.yml' - '--storage.path=/alertmanager' - '--web.external-url=http://localhost:9093' ports: - "9093:9093" volumes: - ../../infra/observability/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro - alertmanager_data:/alertmanager environment: - ALERTMANAGER_SLACK_WEBHOOK_URL=${ALERTMANAGER_SLACK_WEBHOOK_URL:-} - ALERTMANAGER_SMTP_USER=${ALERTMANAGER_SMTP_USER:-} - ALERTMANAGER_SMTP_PASSWORD=${ALERTMANAGER_SMTP_PASSWORD:-} networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:9093/-/healthy || exit 1"] interval: 30s timeout: 10s retries: 3 # Prometheus - Metrics Collection prometheus: image: prom/prometheus:v2.51.0 container_name: prometheus-local command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention.time=15d' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--web.enable-lifecycle' ports: - "9090:9090" volumes: - ../../infra/observability/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ../../infra/observability/prometheus/rules:/etc/prometheus/rules:ro - ../../infra/observability/prometheus/alert-rules.yml:/etc/prometheus/alert-rules.yml:ro - prometheus_data:/prometheus networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:9090/-/healthy || exit 1"] interval: 30s timeout: 10s retries: 3 # Grafana - Metrics Visualization & Dashboards grafana: image: grafana/grafana:10.3.1 container_name: grafana-local ports: - "3002:3000" environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/goodgo-overview.json volumes: - grafana_data:/var/lib/grafana - ../../infra/observability/grafana/datasources:/etc/grafana/provisioning/datasources:ro - ../../infra/observability/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro networks: - microservices-network depends_on: prometheus: condition: service_healthy restart: unless-stopped healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1"] interval: 30s timeout: 10s retries: 3 # Loki - Log Aggregation loki: image: grafana/loki:2.9.4 container_name: loki-local ports: - "3100:3100" command: -config.file=/etc/loki/loki-config.yml volumes: - ../../infra/observability/loki/loki-config.yml:/etc/loki/loki-config.yml:ro - loki_data:/loki networks: - microservices-network restart: unless-stopped # Promtail - Log Collector (ships container logs to Loki) promtail: image: grafana/promtail:3.3.0 container_name: promtail-local volumes: - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock - ../../infra/observability/promtail/promtail-config.yml:/etc/promtail/promtail-config.yml:ro command: -config.file=/etc/promtail/promtail-config.yml networks: - microservices-network depends_on: - loki restart: unless-stopped # =========================================================================== # FRONTEND APPS # =========================================================================== # Web Client TPOS .NET - Blazor WebAssembly Hosted web-client-tpos-net: build: context: ../../ dockerfile: apps/web-client-tpos-net/Dockerfile image: goodgo/web-client-tpos-net:latest container_name: web-client-tpos-net-local environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:8080 # EN: API Gateway URL for backend communication # VI: URL API Gateway để giao tiếp với backend - ApiSettings__GatewayUrl=http://traefik:80 # EN: IAM Service Communication # VI: Giao tiếp IAM Service - IamService__BaseUrl=http://iam-service-net:8080 # EN: YARP Reverse Proxy — override cluster addresses for Docker network # VI: YARP Reverse Proxy — override địa chỉ cluster cho Docker network - ReverseProxy__Clusters__iam-cluster__Destinations__destination1__Address=http://iam-service-net:8080 - ReverseProxy__Clusters__merchant-cluster__Destinations__destination1__Address=http://merchant-service-net:8080 - ReverseProxy__Clusters__catalog-cluster__Destinations__destination1__Address=http://catalog-service-net:8080 - ReverseProxy__Clusters__order-cluster__Destinations__destination1__Address=http://order-service-net:8080 # EN: BFF HTTP Proxy — Forward requests to microservice APIs # VI: BFF HTTP Proxy — Chuyển tiếp request sang microservice APIs - MerchantService__BaseUrl=http://merchant-service-net:8080 - CatalogService__BaseUrl=http://catalog-service-net:8080 - OrderService__BaseUrl=http://order-service-net:8080 - InventoryService__BaseUrl=http://inventory-service-net:8080 - MembershipService__BaseUrl=http://membership-service-net:8080 - WalletService__BaseUrl=http://wallet-service-net:8080 - PromotionService__BaseUrl=http://promotion-service-net:8080 - BookingService__BaseUrl=http://booking-service-net:8080 - FnbEngine__BaseUrl=http://fnb-engine-net:8080 - StorageService__BaseUrl=http://storage-service:8080 ports: - "3001:8080" depends_on: iam-service-net: condition: service_healthy traefik: condition: service_started networks: - microservices-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 30s labels: - "traefik.enable=true" - "traefik.http.routers.web-client.rule=Host(`localhost`)" - "traefik.http.routers.web-client.entrypoints=web" - "traefik.http.routers.web-client.priority=1" - "traefik.http.services.web-client.loadbalancer.server.port=8080" # ============================================================================= # VOLUMES # ============================================================================= volumes: postgres_data: driver: local redis_data: driver: local minio_data: driver: local rabbitmq_data: driver: local prometheus_data: driver: local grafana_data: driver: local loki_data: driver: local alertmanager_data: driver: local # ============================================================================= # NETWORKS # ============================================================================= networks: microservices-network: driver: bridge name: goodgo-network