rwadurian/backend/services/docker-compose.yml

810 lines
28 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# =============================================================================
# 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:
TZ: Asia/Shanghai
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:
# 安全加固: 仅绑定 127.0.0.1, 禁止公网直连数据库
- "127.0.0.1:5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init-databases.sh:/docker-entrypoint-initdb.d/init-databases.sh:ro
# Enable logical replication for Debezium CDC
# Increase max_connections for multiple services + Debezium connectors
command:
- "postgres"
- "-c"
- "wal_level=logical"
- "-c"
- "max_replication_slots=20"
- "-c"
- "max_wal_senders=20"
- "-c"
- "max_connections=300"
- "-c"
# WAL 安全阀: 限制单个 replication slot 最多保留 10GB WAL
# 超过此值 PostgreSQL 会使 slot 失效, 防止磁盘被吃满
# (事故经验: 无此限制, 单个 stuck slot 累积 305GB WAL)
- "max_slot_wal_keep_size=10GB"
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
environment:
TZ: Asia/Shanghai
command: redis-server --appendonly yes --databases 20 ${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:
TZ: Asia/Shanghai
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
# Java timezone for confluentinc images
KAFKA_OPTS: "-Duser.timezone=Asia/Shanghai"
volumes:
- zookeeper_data:/var/lib/zookeeper/data
- zookeeper_log:/var/lib/zookeeper/log
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- /usr/share/zoneinfo:/usr/share/zoneinfo:ro
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"
- "9093:9093"
environment:
TZ: Asia/Shanghai
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092,EXTERNAL://192.168.1.111:9093
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT,EXTERNAL:PLAINTEXT
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,PLAINTEXT_HOST://0.0.0.0:9092,EXTERNAL://0.0.0.0:9093
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
# Java timezone for confluentinc images
KAFKA_OPTS: "-Duser.timezone=Asia/Shanghai"
volumes:
- kafka_data:/var/lib/kafka/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- /usr/share/zoneinfo:/usr/share/zoneinfo:ro
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
# ---------------------------------------------------------------------------
# Debezium Kafka Connect - CDC (Change Data Capture)
# ---------------------------------------------------------------------------
debezium-connect:
# 必须使用 2.5.4.Final+: 修复 DBZ-7316 (WAL 积压 bug)
# 2.4 版本 searchWalPosition 循环不推进 confirmed_flush_lsn
image: debezium/connect:2.5.4.Final
container_name: rwa-debezium-connect
depends_on:
kafka:
condition: service_healthy
postgres:
condition: service_healthy
ports:
# 安全加固: 仅绑定 127.0.0.1, 禁止公网访问 Kafka Connect REST API
# 暴露公网会导致 SSRF 攻击 (恶意注入 connector)
- "127.0.0.1:8084:8083"
environment:
TZ: Asia/Shanghai
GROUP_ID: debezium-connect
BOOTSTRAP_SERVERS: kafka:29092
CONFIG_STORAGE_TOPIC: debezium_configs
OFFSET_STORAGE_TOPIC: debezium_offsets
STATUS_STORAGE_TOPIC: debezium_statuses
CONFIG_STORAGE_REPLICATION_FACTOR: 1
OFFSET_STORAGE_REPLICATION_FACTOR: 1
STATUS_STORAGE_REPLICATION_FACTOR: 1
# Offset 提交频率: 默认 60s, 缩短至 10s 以减少重启后重复处理窗口
OFFSET_FLUSH_INTERVAL_MS: 10000
OFFSET_FLUSH_TIMEOUT_MS: 5000
# Connector settings
KEY_CONVERTER: org.apache.kafka.connect.json.JsonConverter
VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
KEY_CONVERTER_SCHEMAS_ENABLE: "false"
VALUE_CONVERTER_SCHEMAS_ENABLE: "false"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8083/"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
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:
- TZ=Asia/Shanghai
- 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}
# Aliyun SMS Service (阿里云短信服务)
- ALIYUN_ACCESS_KEY_ID=${ALIYUN_ACCESS_KEY_ID}
- ALIYUN_ACCESS_KEY_SECRET=${ALIYUN_ACCESS_KEY_SECRET}
- ALIYUN_SMS_SIGN_NAME=${ALIYUN_SMS_SIGN_NAME:-榴莲皇后}
- ALIYUN_SMS_TEMPLATE_CODE=${ALIYUN_SMS_TEMPLATE_CODE}
- ALIYUN_SMS_ENDPOINT=${ALIYUN_SMS_ENDPOINT:-dysmsapi.aliyuncs.com}
- SMS_ENABLED=${SMS_ENABLED:-false}
# Aliyun KYC Service (阿里云实人认证)
- ALIYUN_KYC_ENABLED=${ALIYUN_KYC_ENABLED:-false}
- ALIYUN_KYC_ENDPOINT=${ALIYUN_KYC_ENDPOINT:-cloudauth.aliyuncs.com}
- ALIYUN_KYC_SCENE_ID=${ALIYUN_KYC_SCENE_ID:-}
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:
- TZ=Asia/Shanghai
- 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
# Identity Service - 用于短信验证和密码验证
- IDENTITY_SERVICE_URL=http://identity-service:3000
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:
- TZ=Asia/Shanghai
- 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:
- TZ=Asia/Shanghai
- 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
# MinIO Object Storage - 用于合同签名和PDF存储
- 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_CONTRACTS=${MINIO_BUCKET_CONTRACTS:-contracts}
- 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: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:
- TZ=Asia/Shanghai
- 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
- WALLET_SERVICE_URL=http://rwa-wallet-service:3001
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:
- TZ=Asia/Shanghai
- 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:
- TZ=Asia/Shanghai
- 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:
- TZ=Asia/Shanghai
- 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
# External Service URLs
- REFERRAL_SERVICE_URL=http://rwa-referral-service:3004
- IDENTITY_SERVICE_URL=http://rwa-identity-service:3000
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:3007/api/v1/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:
- TZ=Asia/Shanghai
- 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
# [2026-01-05] 新增:系统账户报表统计所需的外部服务 URL
- WALLET_SERVICE_URL=http://rwa-wallet-service:3001
- REWARD_SERVICE_URL=http://rwa-reward-service:3005
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:
- TZ=Asia/Shanghai
- 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
# Identity Service - 用于获取用户信息(昵称、头像)
- IDENTITY_SERVICE_URL=http://rwa-identity-service:3000
- IDENTITY_SERVICE_ENABLED=true
# Reward Service - 用于获取月度收益数据
- REWARD_SERVICE_URL=http://rwa-reward-service:3005
- REWARD_SERVICE_ENABLED=true
# 注意:不添加 reward-service 依赖,避免循环依赖
# authorization-service <-> reward-service 互相调用
# 使用 fallback 机制处理服务暂时不可用的情况
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
kafka:
condition: service_started
referral-service:
condition: service_healthy
identity-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:
- TZ=Asia/Shanghai
- 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
- KAFKA_BROKERS=kafka:29092
- KAFKA_CLIENT_ID=admin-service
- KAFKA_CONSUMER_GROUP=admin-service-user-sync
# CDC Consumer (Debezium)
- KAFKA_CDC_CONSUMER_GROUP=admin-service-cdc
# File Storage
- UPLOAD_DIR=/app/uploads
volumes:
- admin_uploads_data:/app/uploads
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
kafka:
condition: service_started
debezium-connect:
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:
- TZ=Asia/Shanghai
- 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=mainnet
# 主网配置 - dUSDT (绿积分) 合约
- KAVA_RPC_URL=https://evm.kava.io
# RPC 故障转移:逗号分隔的多个端点,主端点失败 3 分钟后自动切换
- KAVA_RPC_URLS=${KAVA_RPC_URLS:-https://evm.kava.io,https://evm.kava-rpc.com,https://kava-evm-rpc.publicnode.com,https://rpc.ankr.com/kava_evm}
- KAVA_CHAIN_ID=2222
- KAVA_USDT_CONTRACT=0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3
# BSC 主网 (暂未使用)
# - BSC_RPC_URL=https://bsc-dataseed.binance.org
# - BSC_CHAIN_ID=56
# - BSC_USDT_CONTRACT=0x55d398326f99059fF775485246999027B3197955
# MPC Hot Wallet (用于提现转账)
- MPC_SERVICE_URL=http://rwa-mpc-service:3006
- HOT_WALLET_USERNAME=${HOT_WALLET_USERNAME:-}
- HOT_WALLET_ADDRESS=${HOT_WALLET_ADDRESS:-}
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
admin_uploads_data:
driver: local
zookeeper_data:
driver: local
zookeeper_log:
driver: local
kafka_data:
driver: local
# ===========================================================================
# Networks
# ===========================================================================
networks:
rwa-network:
driver: bridge
mpc-system_mpc-network:
external: true