version: '3.8' services: # ========== Nginx 反向代理 + SSL 终端 ========== # 域名通过 .env 注入,nginx 启动时 envsubst 自动替换模板中的变量 nginx: image: nginx:alpine container_name: youle-nginx ports: - "${NGINX_PORT:-80}:80" - "${NGINX_SSL_PORT:-443}:443" volumes: - ./docker/nginx/default.conf.template:/etc/nginx/templates/default.conf.template:ro - ./docker/nginx/ssl-params.conf:/etc/nginx/snippets/ssl-params.conf:ro - certbot-webroot:/var/www/certbot:ro - certbot-certs:/etc/letsencrypt:ro environment: # 只替换这 3 个变量,不影响 nginx 内置的 $host $scheme 等 NGINX_ENVSUBST_FILTER: "API_DOMAIN|DLWEB_DOMAIN|WX_DOMAIN" API_DOMAIN: ${API_DOMAIN} DLWEB_DOMAIN: ${DLWEB_DOMAIN} WX_DOMAIN: ${WX_DOMAIN} depends_on: - api - dlweb - wxserver restart: unless-stopped networks: - youle-net # ========== Certbot (Let's Encrypt 证书自动续签) ========== # 每 12 小时检查一次证书是否需要续签 certbot: image: certbot/certbot:latest container_name: youle-certbot volumes: - certbot-webroot:/var/www/certbot - certbot-certs:/etc/letsencrypt entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --quiet; sleep 12h & wait $${!}; done'" restart: unless-stopped networks: - youle-net # ========== 网站1: API 服务 (游戏核心接口) ========== # 网站目录: game-docker/api → 容器内 /var/www/html api: build: context: . dockerfile: docker/api/Dockerfile container_name: youle-api ports: - "${API_PORT:-8081}:80" env_file: - .env volumes: - api-logs:/var/www/html/logs - api-source-logs:/var/www/html/source/logs restart: unless-stopped networks: - youle-net # ========== 网站2: DLWEB 服务 (代理管理后台) ========== # 网站目录: game-docker/dlweb/api → 容器内 /var/www/html/api (DocumentRoot) dlweb: build: context: . dockerfile: docker/dlweb/Dockerfile container_name: youle-dlweb ports: - "${DLWEB_PORT:-8082}:80" env_file: - .env volumes: - dlweb-logs:/var/www/html/api/logs - dlweb-debug:/var/www/html/api/ext/debug restart: unless-stopped networks: - youle-net # ========== 网站3: wxserver 服务 (微信小程序后端) ========== # 网站目录: game-docker/wxserver_daoqi → 容器内 /app wxserver: build: context: . dockerfile: docker/wxserver/Dockerfile container_name: youle-wxserver ports: - "${WXSERVER_PORT:-3000}:3000" env_file: - .env environment: - NODE_ENV=production restart: unless-stopped networks: - youle-net # ========== 定时同步任务 (Synchronize.php) ========== # 每 30 秒通过 Docker 内网 POST 请求 dlweb,不走域名/公网流量 syncjob: image: alpine:3.19 container_name: youle-syncjob entrypoint: ["/bin/sh", "/app/sync.sh"] volumes: - ./docker/syncjob/sync.sh:/app/sync.sh:ro - shared-signal:/shared environment: SYNC_URL: "http://dlweb/ext/Synchronize.php" SYNC_INTERVAL: "${SYNC_INTERVAL:-30}" SYNC_PROCESSCOUNT: "${SYNC_PROCESSCOUNT:-200}" depends_on: - dlweb restart: unless-stopped networks: - youle-net # ========== 每日定时任务 (替代 Windows autorun.cmd) ========== # 默认凌晨 4:00 执行报表同步,通过 Docker 内网直连 dlweb cronjob: image: alpine:3.19 container_name: youle-cronjob entrypoint: ["/bin/sh", "/app/entrypoint.sh"] volumes: - ./docker/cronjob/entrypoint.sh:/app/entrypoint.sh:ro - ./docker/cronjob/daily-task.sh:/app/daily-task.sh:ro - shared-signal:/shared environment: DLWEB_INTERNAL_URL: "http://dlweb" CRON_SCHEDULE: "${CRON_SCHEDULE:-0 4 * * *}" depends_on: - dlweb restart: unless-stopped networks: - youle-net # ========== Redis (可选) ========== redis: image: redis:7-alpine container_name: youle-redis command: > redis-server --requirepass ${REDIS_PASSWORD:-123456} --appendonly yes volumes: - redis-data:/data restart: unless-stopped networks: - youle-net volumes: api-logs: api-source-logs: dlweb-logs: dlweb-debug: redis-data: shared-signal: certbot-webroot: certbot-certs: networks: youle-net: driver: bridge