version: '3.8' services: # ==================== 应用服务 ==================== app: build: context: . dockerfile: Dockerfile image: carrotskin/backend:latest container_name: carrotskin-backend restart: unless-stopped ports: - "${APP_PORT:-8080}:8080" environment: # 服务器配置 - SERVER_PORT=8080 - SERVER_MODE=${SERVER_MODE:-release} - SERVER_BASE_PATH=${SERVER_BASE_PATH:-} # 公开访问地址 (用于生成回调URL、邮件链接等) - PUBLIC_URL=${PUBLIC_URL:-http://localhost:8080} # 数据库配置 - DB_HOST=postgres - DB_PORT=5432 - DB_USER=carrotskin - DB_PASSWORD=${DB_PASSWORD:-carrotskin123} - DB_NAME=carrotskin - DB_SSLMODE=disable # Redis 配置 - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=0 # JWT 配置 - JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} - JWT_EXPIRE_HOURS=24 # 存储配置 (RustFS S3兼容) - RUSTFS_ENDPOINT=${RUSTFS_ENDPOINT:-rustfs:9000} - RUSTFS_PUBLIC_URL=${RUSTFS_PUBLIC_URL:-http://localhost:9000} - RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY:-rustfsadmin} - RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY:-rustfsadmin123} - RUSTFS_USE_SSL=${RUSTFS_USE_SSL:-false} - RUSTFS_BUCKET_TEXTURES=${RUSTFS_BUCKET_TEXTURES:-carrotskin} - RUSTFS_BUCKET_AVATARS=${RUSTFS_BUCKET_AVATARS:-carrotskin} # 邮件配置 (可选) - SMTP_HOST=${SMTP_HOST:-} - SMTP_PORT=${SMTP_PORT:-587} - SMTP_USER=${SMTP_USER:-} - SMTP_PASSWORD=${SMTP_PASSWORD:-} - SMTP_FROM=${SMTP_FROM:-} depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - carrotskin-network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/api/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s # ==================== PostgreSQL 数据库 ==================== postgres: image: postgres:16-alpine container_name: carrotskin-postgres restart: unless-stopped environment: - POSTGRES_USER=carrotskin - POSTGRES_PASSWORD=${DB_PASSWORD:-carrotskin123} - POSTGRES_DB=carrotskin - PGDATA=/var/lib/postgresql/data/pgdata volumes: - postgres-data:/var/lib/postgresql/data ports: - "5432:5432" networks: - carrotskin-network healthcheck: test: ["CMD-SHELL", "pg_isready -U carrotskin -d carrotskin"] interval: 10s timeout: 5s retries: 5 start_period: 10s # ==================== Redis 缓存 ==================== redis: image: redis:7-alpine container_name: carrotskin-redis restart: unless-stopped command: > redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru ${REDIS_PASSWORD:+--requirepass ${REDIS_PASSWORD}} volumes: - redis-data:/data ports: - "6379:6379" networks: - carrotskin-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 5s # ==================== RustFS 对象存储 (可选) ==================== rustfs: image: ghcr.io/rustfs/rustfs:latest container_name: carrotskin-rustfs restart: unless-stopped command: > server --address 0.0.0.0:9000 --console-address 0.0.0.0:9001 --access-key ${RUSTFS_ACCESS_KEY:-rustfsadmin} --secret-key ${RUSTFS_SECRET_KEY:-rustfsadmin123} --data /data volumes: - rustfs-data:/data ports: - "9000:9000" # S3 API 端口 - "9001:9001" # 控制台端口 networks: - carrotskin-network healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9000/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s profiles: - storage # 使用 --profile storage 启动 # RustFS 初始化服务 - 自动创建存储桶 rustfs-init: image: minio/mc:latest container_name: carrotskin-rustfs-init depends_on: rustfs: condition: service_healthy entrypoint: > /bin/sh -c " echo '等待 RustFS 启动...'; sleep 5; mc alias set myrustfs http://rustfs:9000 $${RUSTFS_ACCESS_KEY} $${RUSTFS_SECRET_KEY}; mc mb myrustfs/$${RUSTFS_BUCKET} --ignore-existing; mc anonymous set download myrustfs/$${RUSTFS_BUCKET}; echo '存储桶 $${RUSTFS_BUCKET} 创建完成,已设置公开读取权限'; " environment: - RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY:-rustfsadmin} - RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY:-rustfsadmin123} - RUSTFS_BUCKET=${RUSTFS_BUCKET_TEXTURES:-carrotskin} networks: - carrotskin-network profiles: - storage # ==================== 数据卷 ==================== volumes: postgres-data: driver: local redis-data: driver: local rustfs-data: driver: local # ==================== 网络 ==================== networks: carrotskin-network: driver: bridge