# 客服云 — 生产 Docker Compose(适合腾讯云 CVM 单机) # 使用:./deploy/scripts/deploy.sh # 或:docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build name: kefu-prod services: postgres: image: postgres:16-alpine container_name: kefu-prod-db restart: unless-stopped environment: POSTGRES_USER: ${DB_USER:-kefu} POSTGRES_PASSWORD: ${DB_PASSWORD:?请在 deploy/.env.prod 设置 DB_PASSWORD} POSTGRES_DB: ${DB_NAME:-kefu_sys} volumes: - kefu_pgdata:/var/lib/postgresql/data networks: - kefu_net healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-kefu} -d ${DB_NAME:-kefu_sys}"] interval: 10s timeout: 5s retries: 10 start_period: 20s minio: image: minio/minio:latest container_name: kefu-prod-minio restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY:?请设置 STORAGE_ACCESS_KEY} MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_KEY:?请设置 STORAGE_SECRET_KEY} volumes: - kefu_miniodata:/data networks: - kefu_net # 官方镜像极简,无 curl/bash;由 minio-init 重试建桶保证就绪 minio-init: image: minio/mc:latest container_name: kefu-prod-minio-init depends_on: minio: condition: service_started restart: "no" networks: - kefu_net entrypoint: > /bin/sh -c " set -e; i=0; until mc alias set local http://minio:9000 \"$$MINIO_ROOT_USER\" \"$$MINIO_ROOT_PASSWORD\" 2>/dev/null; do i=$$((i+1)); if [ $$i -gt 30 ]; then echo 'minio not ready'; exit 1; fi; echo waiting minio...; sleep 2; done; mc mb -p local/$${STORAGE_BUCKET:-kefu} || true; mc anonymous set download local/$${STORAGE_BUCKET:-kefu}; echo 'MinIO bucket ready'; " environment: MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY} MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_KEY} STORAGE_BUCKET: ${STORAGE_BUCKET:-kefu} api: build: context: . dockerfile: deploy/docker/Dockerfile.api image: kefu-api:${IMAGE_TAG:-latest} container_name: kefu-prod-api restart: unless-stopped depends_on: postgres: condition: service_healthy minio-init: condition: service_completed_successfully environment: SERVER_PORT: "8080" GIN_MODE: ${GIN_MODE:-release} DB_HOST: postgres DB_PORT: "5432" DB_USER: ${DB_USER:-kefu} DB_PASSWORD: ${DB_PASSWORD} DB_NAME: ${DB_NAME:-kefu_sys} DB_SSLMODE: ${DB_SSLMODE:-disable} JWT_SECRET: ${JWT_SECRET:?请设置 JWT_SECRET} STORAGE_ENDPOINT: minio:9000 STORAGE_ACCESS_KEY: ${STORAGE_ACCESS_KEY} STORAGE_SECRET_KEY: ${STORAGE_SECRET_KEY} STORAGE_BUCKET: ${STORAGE_BUCKET:-kefu} STORAGE_USE_SSL: "false" STORAGE_REGION: ${STORAGE_REGION:-us-east-1} # 浏览器访问图片的公网前缀(经 Nginx /files 反代) STORAGE_PUBLIC_BASE_URL: ${STORAGE_PUBLIC_BASE_URL:?请设置 STORAGE_PUBLIC_BASE_URL,如 https://你的域名/files} STORAGE_MAX_UPLOAD_MB: ${STORAGE_MAX_UPLOAD_MB:-10} STORAGE_MAX_IMAGE_EDGE: ${STORAGE_MAX_IMAGE_EDGE:-1920} STORAGE_WEBP_QUALITY: ${STORAGE_WEBP_QUALITY:-80} networks: - kefu_net # 不对外暴露 8080,统一走 nginx web: build: context: . dockerfile: deploy/docker/Dockerfile.web image: kefu-web:${IMAGE_TAG:-latest} container_name: kefu-prod-web restart: unless-stopped depends_on: api: condition: service_healthy minio: condition: service_started ports: - "${HTTP_PORT:-80}:80" networks: - kefu_net # 可选:导入演示数据(profile seed) # docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile seed run --rm seed seed: image: kefu-api:${IMAGE_TAG:-latest} container_name: kefu-prod-seed profiles: ["seed"] depends_on: api: condition: service_healthy environment: DB_HOST: postgres DB_PORT: "5432" DB_USER: ${DB_USER:-kefu} DB_PASSWORD: ${DB_PASSWORD} DB_NAME: ${DB_NAME:-kefu_sys} DB_SSLMODE: ${DB_SSLMODE:-disable} JWT_SECRET: ${JWT_SECRET} STORAGE_ENDPOINT: minio:9000 STORAGE_ACCESS_KEY: ${STORAGE_ACCESS_KEY} STORAGE_SECRET_KEY: ${STORAGE_SECRET_KEY} STORAGE_BUCKET: ${STORAGE_BUCKET:-kefu} STORAGE_USE_SSL: "false" STORAGE_PUBLIC_BASE_URL: ${STORAGE_PUBLIC_BASE_URL} entrypoint: ["/app/seed"] networks: - kefu_net restart: "no" networks: kefu_net: driver: bridge volumes: kefu_pgdata: kefu_miniodata: