services: # MySQL 数据库 mysql: image: mysql:8.0 container_name: ai-cs-mysql environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} MYSQL_DATABASE: ${MYSQL_DATABASE:-ai_cs} MYSQL_USER: ${MYSQL_USER:-ai_cs_user} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-ai_cs_password} ports: - "${MYSQL_PORT:-3306}:3306" volumes: - mysql_data:/var/lib/mysql command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-rootpassword}"] interval: 10s timeout: 5s retries: 5 start_period: 30s networks: - ai-cs-network restart: unless-stopped # 后端服务(使用预构建镜像) backend: image: ${BACKEND_IMAGE:-537yaha/ai-cs-backend:latest} container_name: ai-cs-backend environment: DB_HOST: mysql DB_PORT: 3306 DB_USER: ${MYSQL_USER:-ai_cs_user} DB_PASSWORD: ${MYSQL_PASSWORD:-ai_cs_password} DB_NAME: ${MYSQL_DATABASE:-ai_cs} ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123} SERVER_HOST: 0.0.0.0 SERVER_PORT: 8080 GIN_MODE: ${GIN_MODE:-release} ENCRYPTION_KEY: ${ENCRYPTION_KEY:-default-key} ports: - "${BACKEND_PORT:-18080}:8080" volumes: - ./backend/uploads:/app/uploads depends_on: mysql: condition: service_healthy networks: - ai-cs-network restart: unless-stopped # 前端服务(使用预构建镜像) frontend: image: ${FRONTEND_IMAGE:-537yaha/ai-cs-frontend:latest} container_name: ai-cs-frontend environment: NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8080} ports: - "${FRONTEND_PORT:-3000}:3000" depends_on: - backend networks: - ai-cs-network restart: unless-stopped security_opt: - no-new-privileges:true cap_drop: - ALL cap_add: - NET_BIND_SERVICE read_only: true # 只读文件系统(防止写入恶意文件) tmpfs: - /tmp - /var/tmp - /app/.next/cache # Next.js 需要缓存目录 resources: limits: cpus: '2.0' memory: 2G reservations: cpus: '0.5' memory: 512M volumes: mysql_data: driver: local networks: ai-cs-network: driver: bridge