# ============================================================================= # RWA Backend Services - Docker Compose # ============================================================================= # Usage: # ./deploy.sh up # Start all services # ./deploy.sh down # Stop all services # ./deploy.sh logs # View logs # ./deploy.sh status # Check status # ============================================================================= services: # =========================================================================== # Infrastructure Services # =========================================================================== postgres: image: postgres:16-alpine container_name: rwa-postgres environment: POSTGRES_USER: ${POSTGRES_USER:-rwa_user} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-rwa_secure_password} POSTGRES_MULTIPLE_DATABASES: rwa_identity,rwa_wallet,rwa_mpc,rwa_backup,rwa_planting,rwa_referral,rwa_reward,rwa_leaderboard,rwa_reporting,rwa_authorization,rwa_admin,rwa_presence,rwa_blockchain ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./scripts/init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-rwa_user}"] interval: 5s timeout: 5s retries: 10 restart: unless-stopped networks: - rwa-network redis: image: redis:7-alpine container_name: rwa-redis command: redis-server --appendonly yes ${REDIS_PASSWORD:+--requirepass $REDIS_PASSWORD} ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 10 restart: unless-stopped networks: - rwa-network zookeeper: image: confluentinc/cp-zookeeper:7.5.0 container_name: rwa-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 healthcheck: test: ["CMD", "nc", "-z", "localhost", "2181"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped networks: - rwa-network kafka: image: confluentinc/cp-kafka:7.5.0 container_name: rwa-kafka depends_on: zookeeper: condition: service_healthy ports: - "9092:9092" environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,PLAINTEXT_HOST://0.0.0.0:9092 KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" healthcheck: test: ["CMD", "kafka-topics", "--bootstrap-server", "localhost:9092", "--list"] interval: 30s timeout: 10s retries: 5 start_period: 30s restart: unless-stopped networks: - rwa-network # =========================================================================== # Application Services # =========================================================================== identity-service: build: context: ./identity-service dockerfile: Dockerfile container_name: rwa-identity-service ports: - "3000:3000" environment: - NODE_ENV=production - APP_PORT=3000 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_identity?schema=public - JWT_SECRET=${JWT_SECRET} - JWT_ACCESS_EXPIRES_IN=2h - JWT_REFRESH_EXPIRES_IN=30d - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=0 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=identity-service - KAFKA_GROUP_ID=identity-service-group - WALLET_ENCRYPTION_SALT=${WALLET_ENCRYPTION_SALT} - MPC_SERVICE_URL=http://mpc-service:3006 - MPC_MODE=remote - BACKUP_SERVICE_URL=http://backup-service:3002 - BACKUP_SERVICE_ENABLED=true - SERVICE_JWT_SECRET=${SERVICE_JWT_SECRET} # Blockchain Service (port 3012, with api/v1 prefix) - BLOCKCHAIN_SERVICE_URL=http://blockchain-service:3012/api/v1 # MinIO Object Storage (Server A: 192.168.1.100) - MINIO_ENDPOINT=${MINIO_ENDPOINT:-192.168.1.100} - MINIO_PORT=${MINIO_PORT:-9000} - MINIO_USE_SSL=${MINIO_USE_SSL:-false} - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY:-admin} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY:-minio_secret_password} - MINIO_BUCKET_AVATARS=${MINIO_BUCKET_AVATARS:-avatars} - MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL:-https://minio.szaiai.com} depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network wallet-service: build: context: ./wallet-service dockerfile: Dockerfile container_name: rwa-wallet-service ports: - "3001:3001" environment: - NODE_ENV=production - APP_PORT=3001 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_wallet?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=1 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=wallet-service - KAFKA_GROUP_ID=wallet-service-group depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network backup-service: build: context: ./backup-service dockerfile: Dockerfile container_name: rwa-backup-service ports: - "3002:3002" environment: - NODE_ENV=production - APP_PORT=3002 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_backup?schema=public - SERVICE_JWT_SECRET=${SERVICE_JWT_SECRET} - ALLOWED_SERVICES=identity-service,recovery-service,mpc-service - BACKUP_ENCRYPTION_KEY=${BACKUP_ENCRYPTION_KEY} - BACKUP_ENCRYPTION_KEY_ID=key-v1 - MAX_RETRIEVE_PER_DAY=3 - MAX_STORE_PER_MINUTE=10 depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3002/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network planting-service: build: context: ./planting-service dockerfile: Dockerfile container_name: rwa-planting-service ports: - "3003:3003" environment: - NODE_ENV=production - APP_PORT=3003 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_planting?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=2 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=planting-service - KAFKA_GROUP_ID=planting-service-group - WALLET_SERVICE_URL=http://rwa-wallet-service:3001 - IDENTITY_SERVICE_URL=http://rwa-identity-service:3000 - REFERRAL_SERVICE_URL=http://rwa-referral-service:3004 depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3003/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network referral-service: build: context: ./referral-service dockerfile: Dockerfile container_name: rwa-referral-service ports: - "3004:3004" environment: - NODE_ENV=production - APP_PORT=3004 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_referral?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=3 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=referral-service - KAFKA_GROUP_ID=referral-service-group - AUTHORIZATION_SERVICE_URL=http://rwa-authorization-service:3009 depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started # 注意:不添加 authorization-service 依赖,避免循环依赖 # referral-service <-> authorization-service 互相调用 # 使用 fallback 机制处理服务暂时不可用的情况 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3004/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network reward-service: build: context: ./reward-service dockerfile: Dockerfile container_name: rwa-reward-service ports: - "3005:3005" environment: - NODE_ENV=production - APP_PORT=3005 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_reward?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=4 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=reward-service - KAFKA_GROUP_ID=reward-service-group # External Service URLs - REFERRAL_SERVICE_URL=http://rwa-referral-service:3004 - AUTHORIZATION_SERVICE_URL=http://rwa-authorization-service:3009 - WALLET_SERVICE_URL=http://rwa-wallet-service:3001 depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started referral-service: condition: service_healthy authorization-service: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3005/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network mpc-service: build: context: ./mpc-service dockerfile: Dockerfile container_name: rwa-mpc-service ports: - "3006:3006" environment: - NODE_ENV=production - APP_PORT=3006 # 使用 rwa-postgres 而不是 postgres,避免 mpc-system 网络的 postgres 冲突 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@rwa-postgres:5432/rwa_mpc?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=rwa-redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=5 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=mpc-service - KAFKA_GROUP_ID=mpc-service-group # MPC System - 使用 Docker 网络内部地址 - MPC_ACCOUNT_SERVICE_URL=http://mpc-account-service:8080 - MPC_COORDINATOR_URL=http://mpc-session-coordinator:8080 - MPC_SESSION_COORDINATOR_URL=http://mpc-session-coordinator:8080 - MPC_MESSAGE_ROUTER_WS_URL=ws://mpc-message-router:8080 - MPC_SERVER_PARTY_API_URL=http://mpc-server-party-api:8080 # JWT Secret 必须与 mpc-system 的 JWT_SECRET_KEY 一致 - MPC_JWT_SECRET=change_this_jwt_secret_key_to_random_value_min_32_chars # Blockchain Service - 使用正确的容器名和端口 - BLOCKCHAIN_SERVICE_URL=http://rwa-blockchain-service:3012 - SHARE_MASTER_KEY=${SHARE_MASTER_KEY} # Backup Service - BACKUP_SERVICE_URL=http://backup-service:3002 - BACKUP_SERVICE_ENABLED=true - SERVICE_JWT_SECRET=${SERVICE_JWT_SECRET} depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3006/api/v1/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network - mpc-system_mpc-network leaderboard-service: build: context: ./leaderboard-service dockerfile: Dockerfile container_name: rwa-leaderboard-service ports: - "3007:3007" environment: - NODE_ENV=production - APP_PORT=3007 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_leaderboard?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=6 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=leaderboard-service - KAFKA_GROUP_ID=leaderboard-service-group depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3007/api/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network reporting-service: build: context: ./reporting-service dockerfile: Dockerfile container_name: rwa-reporting-service ports: - "3008:3008" environment: - NODE_ENV=production - APP_PORT=3008 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_reporting?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=7 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=reporting-service - KAFKA_GROUP_ID=reporting-service-group depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3008/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network authorization-service: build: context: ./authorization-service dockerfile: Dockerfile container_name: rwa-authorization-service ports: - "3009:3009" environment: - NODE_ENV=production - APP_PORT=3009 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_authorization?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=8 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=authorization-service - KAFKA_GROUP_ID=authorization-service-group # Referral Service - 用于获取团队统计数据 - REFERRAL_SERVICE_URL=http://rwa-referral-service:3004 - REFERRAL_SERVICE_ENABLED=true depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started referral-service: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3009/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network admin-service: build: context: ./admin-service dockerfile: Dockerfile container_name: rwa-admin-service ports: - "3010:3010" environment: - NODE_ENV=production - APP_PORT=3010 - BASE_URL=https://rwaapi.szaiai.com - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_admin?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=9 depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3010/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network presence-service: build: context: ./presence-service dockerfile: Dockerfile container_name: rwa-presence-service ports: - "3011:3011" environment: - NODE_ENV=production - APP_PORT=3011 - API_PREFIX=api/v1 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_presence?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=10 - KAFKA_ENABLED=true - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=presence-service - KAFKA_GROUP_ID=presence-service-group - PRESENCE_WINDOW_SECONDS=180 - SNAPSHOT_INTERVAL_SECONDS=60 - TZ=Asia/Shanghai depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3011/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 40s restart: unless-stopped networks: - rwa-network blockchain-service: build: context: ./blockchain-service dockerfile: Dockerfile container_name: rwa-blockchain-service ports: - "3012:3012" environment: - NODE_ENV=production - APP_PORT=3012 - API_PREFIX=api/v1 - DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_blockchain?schema=public - JWT_SECRET=${JWT_SECRET} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=11 - KAFKA_BROKERS=kafka:29092 - KAFKA_CLIENT_ID=blockchain-service - KAFKA_GROUP_ID=blockchain-service-group # 网络模式: mainnet 或 testnet - NETWORK_MODE=testnet # 主网配置 (NETWORK_MODE=mainnet 时使用) # - KAVA_RPC_URL=https://evm.kava.io # - KAVA_CHAIN_ID=2222 # - KAVA_USDT_CONTRACT=0x919C1c267BC06a7039e03fcc2eF738525769109c # - BSC_RPC_URL=https://bsc-dataseed.binance.org # - BSC_CHAIN_ID=56 # - BSC_USDT_CONTRACT=0x55d398326f99059fF775485246999027B3197955 # 测试网配置 (NETWORK_MODE=testnet 时使用) # - KAVA_RPC_URL=https://evm.testnet.kava.io # - KAVA_CHAIN_ID=2221 # - BSC_RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545 # - BSC_CHAIN_ID=97 # - BSC_USDT_CONTRACT=0x337610d27c682E347C9cD60BD4b3b107C9d34dDd depends_on: postgres: condition: service_healthy redis: condition: service_healthy kafka: condition: service_started healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3012/api/v1/health"] interval: 30s timeout: 3s retries: 3 start_period: 60s restart: unless-stopped networks: - rwa-network # =========================================================================== # Volumes # =========================================================================== volumes: postgres_data: driver: local redis_data: driver: local # =========================================================================== # Networks # =========================================================================== networks: rwa-network: driver: bridge mpc-system_mpc-network: external: true