feat(services): add unified Docker deployment system
- Add docker-compose.yml for all 11 backend services - Add deploy.sh automation script with install/build/up/down commands - Add init-databases.sh for PostgreSQL multi-database initialization - Add .env.example template with secure key placeholders - Fix empty Dockerfiles for admin/referral/reporting/wallet services Services included: - identity-service (:3000) - wallet-service (:3001) - backup-service (:3002) - planting-service (:3003) - referral-service (:3004) - reward-service (:3005) - mpc-service (:3006) - leaderboard-service (:3007) - reporting-service (:3008) - authorization-service (:3009) - admin-service (:3010) Infrastructure: PostgreSQL, Redis, Kafka/Zookeeper 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7d257cd35f
commit
f99cac21cf
|
|
@ -0,0 +1,32 @@
|
||||||
|
# =============================================================================
|
||||||
|
# RWA Backend Services - Environment Configuration Template
|
||||||
|
# =============================================================================
|
||||||
|
# Copy this file to .env and fill in the values
|
||||||
|
# WARNING: Never commit .env to version control!
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# PostgreSQL Database
|
||||||
|
POSTGRES_USER=rwa_user
|
||||||
|
POSTGRES_PASSWORD=your_secure_password_here
|
||||||
|
|
||||||
|
# Redis (leave empty for no password)
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
|
||||||
|
# JWT Configuration (generate with: openssl rand -base64 32)
|
||||||
|
JWT_SECRET=your_jwt_secret_here
|
||||||
|
|
||||||
|
# Service-to-Service Authentication
|
||||||
|
SERVICE_JWT_SECRET=your_service_jwt_secret_here
|
||||||
|
|
||||||
|
# Wallet Encryption Salt
|
||||||
|
WALLET_ENCRYPTION_SALT=your_wallet_salt_here
|
||||||
|
|
||||||
|
# Backup Encryption Key (256-bit hex: openssl rand -hex 32)
|
||||||
|
BACKUP_ENCRYPTION_KEY=your_64_char_hex_key_here
|
||||||
|
|
||||||
|
# MPC Share Master Key (256-bit hex: openssl rand -hex 32)
|
||||||
|
SHARE_MASTER_KEY=your_64_char_hex_key_here
|
||||||
|
|
||||||
|
# MPC System Address (running on 192.168.1.100)
|
||||||
|
MPC_COORDINATOR_URL=http://192.168.1.100:8081
|
||||||
|
MPC_MESSAGE_ROUTER_URL=ws://192.168.1.100:8082
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Environment files (contain secrets)
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# Docker volumes (if local)
|
||||||
|
postgres_data/
|
||||||
|
redis_data/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
# RWA Backend Services
|
||||||
|
|
||||||
|
统一部署管理 RWA 后端微服务。
|
||||||
|
|
||||||
|
## 架构概览
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 192.168.1.100 (Gateway) │
|
||||||
|
│ ┌─────────────┐ ┌─────────────────────────────────────────┐ │
|
||||||
|
│ │ Nginx │ │ MPC-System (Go) │ │
|
||||||
|
│ │ (Reverse │ │ - session-coordinator (:8081) │ │
|
||||||
|
│ │ Proxy) │ │ - message-router (:8082) │ │
|
||||||
|
│ │ │ │ - server-party-1/2/3 (:8083-8085) │ │
|
||||||
|
│ └─────────────┘ │ - account-service (:8080) │ │
|
||||||
|
│ └─────────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
│ Internal Network
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 192.168.1.111 (Backend) │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Docker Compose Services │ │
|
||||||
|
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||||||
|
│ │ │ PostgreSQL │ │ Redis │ │ Kafka │ │ │
|
||||||
|
│ │ │ (:5432) │ │ (:6379) │ │ (:9092) │ │ │
|
||||||
|
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||||||
|
│ │ │ identity │ │ wallet │ │ backup │ │ │
|
||||||
|
│ │ │ (:3000) │ │ (:3001) │ │ (:3002) │ │ │
|
||||||
|
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||||||
|
│ │ │ planting │ │ referral │ │ reward │ │ │
|
||||||
|
│ │ │ (:3003) │ │ (:3004) │ │ (:3005) │ │ │
|
||||||
|
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||||||
|
│ │ │ mpc │ │ leaderboard │ │ reporting │ │ │
|
||||||
|
│ │ │ (:3006) │ │ (:3007) │ │ (:3008) │ │ │
|
||||||
|
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ ┌─────────────┐ ┌─────────────┐ │ │
|
||||||
|
│ │ │authorization│ │ admin │ │ │
|
||||||
|
│ │ │ (:3009) │ │ (:3010) │ │ │
|
||||||
|
│ │ └─────────────┘ └─────────────┘ │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 首次安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入服务目录
|
||||||
|
cd ~/rwadurian/backend/services
|
||||||
|
|
||||||
|
# 运行安装(自动生成安全密钥)
|
||||||
|
./deploy.sh install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 构建镜像
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./deploy.sh build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 启动服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./deploy.sh up
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 检查状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./deploy.sh status
|
||||||
|
./deploy.sh health
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
| 命令 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `./deploy.sh install` | 首次安装,生成配置 |
|
||||||
|
| `./deploy.sh build` | 构建所有 Docker 镜像 |
|
||||||
|
| `./deploy.sh up` | 启动所有服务 |
|
||||||
|
| `./deploy.sh down` | 停止所有服务 |
|
||||||
|
| `./deploy.sh restart` | 重启所有服务 |
|
||||||
|
| `./deploy.sh status` | 查看服务状态 |
|
||||||
|
| `./deploy.sh health` | 检查服务健康 |
|
||||||
|
| `./deploy.sh logs` | 查看所有日志 |
|
||||||
|
| `./deploy.sh logs <service>` | 查看指定服务日志 |
|
||||||
|
| `./deploy.sh migrate` | 运行数据库迁移 |
|
||||||
|
| `./deploy.sh rebuild-svc <name>` | 重建指定服务 |
|
||||||
|
|
||||||
|
## 服务列表
|
||||||
|
|
||||||
|
| 服务 | 端口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| identity-service | 3000 | 身份认证服务 |
|
||||||
|
| wallet-service | 3001 | 钱包账本服务 |
|
||||||
|
| backup-service | 3002 | MPC 备份服务 |
|
||||||
|
| planting-service | 3003 | 认种服务 |
|
||||||
|
| referral-service | 3004 | 推荐系统服务 |
|
||||||
|
| reward-service | 3005 | 奖励服务 |
|
||||||
|
| mpc-service | 3006 | MPC 中间层服务 |
|
||||||
|
| leaderboard-service | 3007 | 排行榜服务 |
|
||||||
|
| reporting-service | 3008 | 报表服务 |
|
||||||
|
| authorization-service | 3009 | 授权服务 |
|
||||||
|
| admin-service | 3010 | 管理后台服务 |
|
||||||
|
|
||||||
|
## 基础设施
|
||||||
|
|
||||||
|
| 服务 | 端口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| PostgreSQL | 5432 | 主数据库 |
|
||||||
|
| Redis | 6379 | 缓存/会话 |
|
||||||
|
| Kafka | 9092 | 消息队列 |
|
||||||
|
| Zookeeper | 2181 | Kafka 协调 |
|
||||||
|
|
||||||
|
## 环境配置
|
||||||
|
|
||||||
|
配置文件 `.env` 由 `./deploy.sh install` 自动生成,包含:
|
||||||
|
|
||||||
|
- 数据库密码
|
||||||
|
- JWT 密钥
|
||||||
|
- 加密密钥
|
||||||
|
- MPC 系统地址
|
||||||
|
|
||||||
|
**重要**: `.env` 文件包含敏感信息,请勿提交到 Git!
|
||||||
|
|
||||||
|
## 与 MPC-System 集成
|
||||||
|
|
||||||
|
mpc-service 需要连接到运行在 192.168.1.100 上的 MPC-System:
|
||||||
|
|
||||||
|
- Session Coordinator: `http://192.168.1.100:8081`
|
||||||
|
- Message Router: `ws://192.168.1.100:8082`
|
||||||
|
|
||||||
|
确保 192.168.1.111 能够访问 192.168.1.100 的这些端口。
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 查看服务日志
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./deploy.sh logs identity-service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 重建单个服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./deploy.sh rebuild-svc mpc-service
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据库连接问题
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入 postgres 容器
|
||||||
|
docker exec -it rwa-postgres psql -U rwa_user -d rwa_identity
|
||||||
|
```
|
||||||
|
|
||||||
|
### 清理重新开始
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./deploy.sh clean # 删除所有容器和数据
|
||||||
|
./deploy.sh install
|
||||||
|
./deploy.sh build
|
||||||
|
./deploy.sh up
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# =============================================================================
|
||||||
|
# Admin Service Dockerfile
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
COPY tsconfig*.json ./
|
||||||
|
COPY nest-cli.json ./
|
||||||
|
|
||||||
|
# Copy Prisma schema if exists
|
||||||
|
COPY prisma ./prisma/ 2>/dev/null || true
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Generate Prisma client if schema exists
|
||||||
|
RUN if [ -f "prisma/schema.prisma" ]; then npx prisma generate; fi
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# Build TypeScript
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install production dependencies only
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy Prisma schema and generate client if exists
|
||||||
|
COPY prisma ./prisma/ 2>/dev/null || true
|
||||||
|
RUN if [ -f "prisma/schema.prisma" ]; then npx prisma generate; fi
|
||||||
|
|
||||||
|
# Copy built files
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nestjs -u 1001
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nestjs
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 3010
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||||
|
CMD wget -q --spider http://localhost:3010/health || exit 1
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
CMD ["node", "dist/main.js"]
|
||||||
|
|
@ -0,0 +1,470 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# RWA Backend Services - Deployment Script
|
||||||
|
# =========================================
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./deploy.sh install # First time setup (generate secrets, init databases)
|
||||||
|
# ./deploy.sh up # Start all services
|
||||||
|
# ./deploy.sh down # Stop all services
|
||||||
|
# ./deploy.sh restart # Restart all services
|
||||||
|
# ./deploy.sh status # Show service status
|
||||||
|
# ./deploy.sh logs [svc] # View logs (optional: specific service)
|
||||||
|
# ./deploy.sh build # Rebuild all images
|
||||||
|
# ./deploy.sh migrate # Run database migrations
|
||||||
|
# ./deploy.sh health # Check health of all services
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Configuration
|
||||||
|
# ===========================================================================
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ENV_FILE="$SCRIPT_DIR/.env"
|
||||||
|
COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml"
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Helper Functions
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
generate_random_password() {
|
||||||
|
openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_hex_key() {
|
||||||
|
openssl rand -hex 32
|
||||||
|
}
|
||||||
|
|
||||||
|
check_docker() {
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
log_error "Docker is not installed. Please install Docker first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! docker compose version &> /dev/null; then
|
||||||
|
log_error "Docker Compose is not installed. Please install Docker Compose first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Docker version: $(docker --version)"
|
||||||
|
log_info "Docker Compose version: $(docker compose version --short)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Install / Initialize
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
install() {
|
||||||
|
log_step "Installing RWA Backend Services..."
|
||||||
|
|
||||||
|
check_docker
|
||||||
|
|
||||||
|
# Generate .env file if not exists
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
log_step "Generating secure configuration..."
|
||||||
|
|
||||||
|
POSTGRES_PASSWORD=$(generate_random_password)
|
||||||
|
JWT_SECRET=$(generate_random_password)
|
||||||
|
SERVICE_JWT_SECRET=$(generate_random_password)
|
||||||
|
WALLET_ENCRYPTION_SALT=$(generate_random_password)
|
||||||
|
BACKUP_ENCRYPTION_KEY=$(generate_hex_key)
|
||||||
|
SHARE_MASTER_KEY=$(generate_hex_key)
|
||||||
|
|
||||||
|
cat > "$ENV_FILE" << EOF
|
||||||
|
# =============================================================================
|
||||||
|
# RWA Backend Services - Production Environment Configuration
|
||||||
|
# =============================================================================
|
||||||
|
# Generated: $(date)
|
||||||
|
# WARNING: Keep this file secure! Do not commit to version control!
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# PostgreSQL Database
|
||||||
|
POSTGRES_USER=rwa_user
|
||||||
|
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
|
||||||
|
# Redis (leave empty for no password)
|
||||||
|
REDIS_PASSWORD=
|
||||||
|
|
||||||
|
# JWT Configuration
|
||||||
|
JWT_SECRET=${JWT_SECRET}
|
||||||
|
|
||||||
|
# Service-to-Service Authentication
|
||||||
|
SERVICE_JWT_SECRET=${SERVICE_JWT_SECRET}
|
||||||
|
|
||||||
|
# Wallet Encryption
|
||||||
|
WALLET_ENCRYPTION_SALT=${WALLET_ENCRYPTION_SALT}
|
||||||
|
|
||||||
|
# Backup Encryption (256-bit hex key)
|
||||||
|
BACKUP_ENCRYPTION_KEY=${BACKUP_ENCRYPTION_KEY}
|
||||||
|
|
||||||
|
# MPC Share Master Key (256-bit hex key)
|
||||||
|
SHARE_MASTER_KEY=${SHARE_MASTER_KEY}
|
||||||
|
|
||||||
|
# MPC System Address (on 192.168.1.100)
|
||||||
|
MPC_COORDINATOR_URL=http://192.168.1.100:8081
|
||||||
|
MPC_MESSAGE_ROUTER_URL=ws://192.168.1.100:8082
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 600 "$ENV_FILE"
|
||||||
|
log_info "Environment file created: $ENV_FILE"
|
||||||
|
log_info "Secrets have been auto-generated"
|
||||||
|
else
|
||||||
|
log_info "Environment file already exists: $ENV_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create scripts directory
|
||||||
|
mkdir -p "$SCRIPT_DIR/scripts"
|
||||||
|
|
||||||
|
# Create database init script
|
||||||
|
create_db_init_script
|
||||||
|
|
||||||
|
log_info "Installation complete!"
|
||||||
|
log_info ""
|
||||||
|
log_info "Next steps:"
|
||||||
|
log_info " 1. Review and edit .env if needed"
|
||||||
|
log_info " 2. Run: ./deploy.sh build"
|
||||||
|
log_info " 3. Run: ./deploy.sh up"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_db_init_script() {
|
||||||
|
cat > "$SCRIPT_DIR/scripts/init-databases.sh" << 'DBSCRIPT'
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to create database if not exists
|
||||||
|
create_database() {
|
||||||
|
local database=$1
|
||||||
|
echo "Creating database: $database"
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
|
||||||
|
SELECT 'CREATE DATABASE $database'
|
||||||
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$database')\gexec
|
||||||
|
EOSQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create all required databases
|
||||||
|
for db in rwa_identity rwa_wallet rwa_mpc rwa_backup rwa_planting rwa_referral rwa_reward rwa_leaderboard rwa_reporting rwa_authorization; do
|
||||||
|
create_database "$db"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "All databases created successfully!"
|
||||||
|
DBSCRIPT
|
||||||
|
|
||||||
|
chmod +x "$SCRIPT_DIR/scripts/init-databases.sh"
|
||||||
|
log_info "Database init script created"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Docker Compose Operations
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
up() {
|
||||||
|
log_step "Starting RWA Backend Services..."
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
log_error "Environment file not found. Run './deploy.sh install' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start infrastructure first
|
||||||
|
log_info "Starting infrastructure services..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d postgres redis zookeeper kafka
|
||||||
|
|
||||||
|
# Wait for infrastructure
|
||||||
|
log_info "Waiting for infrastructure to be ready..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Start application services
|
||||||
|
log_info "Starting application services..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d
|
||||||
|
|
||||||
|
log_info "All services started!"
|
||||||
|
log_info ""
|
||||||
|
log_info "Check status with: ./deploy.sh status"
|
||||||
|
log_info "View logs with: ./deploy.sh logs"
|
||||||
|
}
|
||||||
|
|
||||||
|
down() {
|
||||||
|
log_step "Stopping RWA Backend Services..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down
|
||||||
|
log_info "All services stopped"
|
||||||
|
}
|
||||||
|
|
||||||
|
restart() {
|
||||||
|
log_step "Restarting RWA Backend Services..."
|
||||||
|
down
|
||||||
|
sleep 3
|
||||||
|
up
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
log_step "Building Docker images..."
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
log_error "Environment file not found. Run './deploy.sh install' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build --parallel
|
||||||
|
log_info "All images built successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Status and Monitoring
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
status() {
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "RWA Backend Services Status"
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo "Service Health Check"
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
health
|
||||||
|
}
|
||||||
|
|
||||||
|
health() {
|
||||||
|
local services=(
|
||||||
|
"identity-service:3000"
|
||||||
|
"wallet-service:3001"
|
||||||
|
"backup-service:3002"
|
||||||
|
"planting-service:3003"
|
||||||
|
"referral-service:3004"
|
||||||
|
"reward-service:3005"
|
||||||
|
"mpc-service:3006"
|
||||||
|
"leaderboard-service:3007"
|
||||||
|
"reporting-service:3008"
|
||||||
|
"authorization-service:3009"
|
||||||
|
"admin-service:3010"
|
||||||
|
)
|
||||||
|
|
||||||
|
for svc in "${services[@]}"; do
|
||||||
|
name="${svc%%:*}"
|
||||||
|
port="${svc##*:}"
|
||||||
|
|
||||||
|
if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port/health" 2>/dev/null | grep -q "200"; then
|
||||||
|
echo -e "${GREEN}[OK]${NC} $name (port $port)"
|
||||||
|
else
|
||||||
|
echo -e "${RED}[FAIL]${NC} $name (port $port)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Infrastructure health
|
||||||
|
echo "Infrastructure:"
|
||||||
|
|
||||||
|
if docker exec rwa-postgres pg_isready -U rwa_user &>/dev/null; then
|
||||||
|
echo -e " ${GREEN}[OK]${NC} PostgreSQL"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}[FAIL]${NC} PostgreSQL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker exec rwa-redis redis-cli ping &>/dev/null; then
|
||||||
|
echo -e " ${GREEN}[OK]${NC} Redis"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}[FAIL]${NC} Redis"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker exec rwa-kafka kafka-topics --bootstrap-server localhost:9092 --list &>/dev/null; then
|
||||||
|
echo -e " ${GREEN}[OK]${NC} Kafka"
|
||||||
|
else
|
||||||
|
echo -e " ${RED}[FAIL]${NC} Kafka"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
logs() {
|
||||||
|
local service="$1"
|
||||||
|
|
||||||
|
if [ -n "$service" ]; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f "$service"
|
||||||
|
else
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Database Operations
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
migrate() {
|
||||||
|
log_step "Running database migrations..."
|
||||||
|
|
||||||
|
local services=(
|
||||||
|
"identity-service"
|
||||||
|
"wallet-service"
|
||||||
|
"backup-service"
|
||||||
|
"planting-service"
|
||||||
|
"referral-service"
|
||||||
|
"reward-service"
|
||||||
|
"mpc-service"
|
||||||
|
"leaderboard-service"
|
||||||
|
"reporting-service"
|
||||||
|
"authorization-service"
|
||||||
|
)
|
||||||
|
|
||||||
|
for svc in "${services[@]}"; do
|
||||||
|
log_info "Running migrations for $svc..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec "$svc" npx prisma migrate deploy 2>/dev/null || \
|
||||||
|
log_warn "Migration skipped for $svc (no migrations or service not running)"
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "Migrations complete"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Cleanup
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
clean() {
|
||||||
|
log_warn "This will remove all containers, volumes, and images!"
|
||||||
|
read -p "Are you sure? (y/N): " confirm
|
||||||
|
|
||||||
|
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
|
||||||
|
log_step "Cleaning up..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down -v --rmi all
|
||||||
|
log_info "Cleanup complete"
|
||||||
|
else
|
||||||
|
log_info "Cleanup cancelled"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Single Service Operations
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
start_service() {
|
||||||
|
local service="$1"
|
||||||
|
if [ -z "$service" ]; then
|
||||||
|
log_error "Please specify a service name"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Starting $service..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d "$service"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_service() {
|
||||||
|
local service="$1"
|
||||||
|
if [ -z "$service" ]; then
|
||||||
|
log_error "Please specify a service name"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Stopping $service..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" stop "$service"
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild_service() {
|
||||||
|
local service="$1"
|
||||||
|
if [ -z "$service" ]; then
|
||||||
|
log_error "Please specify a service name"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Rebuilding $service..."
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build "$service"
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d "$service"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Main
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
install)
|
||||||
|
install
|
||||||
|
;;
|
||||||
|
up|start)
|
||||||
|
up
|
||||||
|
;;
|
||||||
|
down|stop)
|
||||||
|
down
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
restart
|
||||||
|
;;
|
||||||
|
build)
|
||||||
|
build
|
||||||
|
;;
|
||||||
|
status|ps)
|
||||||
|
status
|
||||||
|
;;
|
||||||
|
health)
|
||||||
|
health
|
||||||
|
;;
|
||||||
|
logs)
|
||||||
|
logs "$2"
|
||||||
|
;;
|
||||||
|
migrate)
|
||||||
|
migrate
|
||||||
|
;;
|
||||||
|
clean)
|
||||||
|
clean
|
||||||
|
;;
|
||||||
|
start-svc)
|
||||||
|
start_service "$2"
|
||||||
|
;;
|
||||||
|
stop-svc)
|
||||||
|
stop_service "$2"
|
||||||
|
;;
|
||||||
|
rebuild-svc)
|
||||||
|
rebuild_service "$2"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "RWA Backend Services Deployment Script"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $0 <command> [options]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " install - First time setup (generate secrets, create configs)"
|
||||||
|
echo " up/start - Start all services"
|
||||||
|
echo " down/stop - Stop all services"
|
||||||
|
echo " restart - Restart all services"
|
||||||
|
echo " build - Build all Docker images"
|
||||||
|
echo " status/ps - Show service status"
|
||||||
|
echo " health - Check health of all services"
|
||||||
|
echo " logs [svc] - View logs (optionally for specific service)"
|
||||||
|
echo " migrate - Run database migrations"
|
||||||
|
echo " clean - Remove all containers, volumes, and images"
|
||||||
|
echo ""
|
||||||
|
echo "Single Service Commands:"
|
||||||
|
echo " start-svc <name> - Start a specific service"
|
||||||
|
echo " stop-svc <name> - Stop a specific service"
|
||||||
|
echo " rebuild-svc <name> - Rebuild and restart a specific service"
|
||||||
|
echo ""
|
||||||
|
echo "Services:"
|
||||||
|
echo " identity-service, wallet-service, backup-service, planting-service,"
|
||||||
|
echo " referral-service, reward-service, mpc-service, leaderboard-service,"
|
||||||
|
echo " reporting-service, authorization-service, admin-service"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 install # First time setup"
|
||||||
|
echo " $0 build # Build images"
|
||||||
|
echo " $0 up # Start all services"
|
||||||
|
echo " $0 logs identity-service # View identity-service logs"
|
||||||
|
echo " $0 rebuild-svc mpc-service # Rebuild specific service"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
@ -0,0 +1,510 @@
|
||||||
|
# =============================================================================
|
||||||
|
# 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
|
||||||
|
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}
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
kafka:
|
||||||
|
condition: service_started
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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", "wget", "-q", "--spider", "http://localhost:3001/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
- 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", "-q", "--spider", "http://localhost:3002/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
kafka:
|
||||||
|
condition: service_started
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3003/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
kafka:
|
||||||
|
condition: service_started
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3004/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
kafka:
|
||||||
|
condition: service_started
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3005/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
- DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_mpc?schema=public
|
||||||
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
|
- REDIS_HOST=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_COORDINATOR_URL=http://192.168.1.100:8081
|
||||||
|
- MPC_MESSAGE_ROUTER_WS_URL=ws://192.168.1.100:8082
|
||||||
|
- SHARE_MASTER_KEY=${SHARE_MASTER_KEY}
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
kafka:
|
||||||
|
condition: service_started
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3006/api/v1/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- rwa-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", "wget", "-q", "--spider", "http://localhost:3007/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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", "wget", "-q", "--spider", "http://localhost:3008/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
kafka:
|
||||||
|
condition: service_started
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3009/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
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
|
||||||
|
- DATABASE_URL=postgresql://${POSTGRES_USER:-rwa_user}:${POSTGRES_PASSWORD:-rwa_secure_password}@postgres:5432/rwa_identity?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", "wget", "-q", "--spider", "http://localhost:3010/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- rwa-network
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Volumes
|
||||||
|
# ===========================================================================
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
driver: local
|
||||||
|
redis_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Networks
|
||||||
|
# ===========================================================================
|
||||||
|
networks:
|
||||||
|
rwa-network:
|
||||||
|
driver: bridge
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# =============================================================================
|
||||||
|
# Referral Service Dockerfile
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
COPY tsconfig*.json ./
|
||||||
|
COPY nest-cli.json ./
|
||||||
|
|
||||||
|
# Copy Prisma schema
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Generate Prisma client
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# Build TypeScript
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install production dependencies only
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy Prisma schema and generate client
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy built files
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nestjs -u 1001
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nestjs
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 3004
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||||
|
CMD wget -q --spider http://localhost:3004/health || exit 1
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
CMD ["node", "dist/main.js"]
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# =============================================================================
|
||||||
|
# Reporting Service Dockerfile
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
COPY tsconfig*.json ./
|
||||||
|
COPY nest-cli.json ./
|
||||||
|
|
||||||
|
# Copy Prisma schema
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Generate Prisma client
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# Build TypeScript
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install production dependencies only
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy Prisma schema and generate client
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy built files
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nestjs -u 1001
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nestjs
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 3008
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||||
|
CMD wget -q --spider http://localhost:3008/health || exit 1
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
CMD ["node", "dist/main.js"]
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to create database if not exists
|
||||||
|
create_database() {
|
||||||
|
local database=$1
|
||||||
|
echo "Creating database: $database"
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
|
||||||
|
SELECT 'CREATE DATABASE $database'
|
||||||
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '$database')\gexec
|
||||||
|
EOSQL
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create all required databases
|
||||||
|
for db in rwa_identity rwa_wallet rwa_mpc rwa_backup rwa_planting rwa_referral rwa_reward rwa_leaderboard rwa_reporting rwa_authorization; do
|
||||||
|
create_database "$db"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "All databases created successfully!"
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# =============================================================================
|
||||||
|
# Wallet Service Dockerfile
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Build stage
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
COPY tsconfig*.json ./
|
||||||
|
COPY nest-cli.json ./
|
||||||
|
|
||||||
|
# Copy Prisma schema
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Generate Prisma client
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# Build TypeScript
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install production dependencies only
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
# Copy Prisma schema and generate client
|
||||||
|
COPY prisma ./prisma/
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
# Copy built files
|
||||||
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nestjs -u 1001
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nestjs
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 3001
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||||
|
CMD wget -q --spider http://localhost:3001/health || exit 1
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
CMD ["node", "dist/main.js"]
|
||||||
Loading…
Reference in New Issue