Files
pos-system/microservices/deployments/local/docker-compose.yml
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

1645 lines
62 KiB
YAML

# =============================================================================
# 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