version: '3.8' services: # MySQL数据库 mysql: image: mysql:8.0 container_name: equipment-mysql restart: always environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-change-me-local-password} MYSQL_DATABASE: ${MYSQL_DATABASE:-equipment_management} MYSQL_CHARSET: utf8mb4 MYSQL_COLLATION: utf8mb4_unicode_ci ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci healthcheck: test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -p\"$$MYSQL_ROOT_PASSWORD\""] interval: 10s timeout: 5s retries: 5 # 后端服务 backend: build: context: ./backend dockerfile: Dockerfile container_name: equipment-backend restart: always ports: - "3000:3000" environment: DATABASE_URL: mysql://root:${MYSQL_ROOT_PASSWORD:-change-me-local-password}@mysql:3306/${MYSQL_DATABASE:-equipment_management}?charset=utf8mb4 NODE_ENV: production SESSION_SECRET: ${SESSION_SECRET:?SESSION_SECRET must be set} SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-} AUTH_MODE: ${AUTH_MODE:-local} KEYCLOAK_URL: ${KEYCLOAK_URL:-} KEYCLOAK_REALM: ${KEYCLOAK_REALM:-} KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID:-} KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET:-} PORT: ${PORT:-3000} SQLSERVER_HOST: ${SQLSERVER_HOST:-} SQLSERVER_PORT: ${SQLSERVER_PORT:-1433} SQLSERVER_DATABASE: ${SQLSERVER_DATABASE:-} SQLSERVER_USER: ${SQLSERVER_USER:-} SQLSERVER_PASSWORD: ${SQLSERVER_PASSWORD:-} SQLSERVER_SCHEMA: ${SQLSERVER_SCHEMA:-rpt} SQLSERVER_ENCRYPT: ${SQLSERVER_ENCRYPT:-false} SQLSERVER_TRUST_CERT: ${SQLSERVER_TRUST_CERT:-true} HR_SYNC_ENABLED: ${HR_SYNC_ENABLED:-false} HR_SYNC_SCHEDULE: ${HR_SYNC_SCHEDULE:-03:00} HR_SYNC_SCHEDULES: ${HR_SYNC_SCHEDULES:-} HR_SYNC_ALLOWED_STATUS_VALUES: ${HR_SYNC_ALLOWED_STATUS_VALUES:-2,3} HR_SYNC_INACTIVE_STATUS_VALUES: ${HR_SYNC_INACTIVE_STATUS_VALUES:-5} HR_SYNC_EXCLUDED_DEPARTMENTS: ${HR_SYNC_EXCLUDED_DEPARTMENTS:-供应商,快递公司,外部交流} HR_SYNC_EXCLUDED_NAME_KEYWORDS: ${HR_SYNC_EXCLUDED_NAME_KEYWORDS:-} APP_PUBLIC_BASE_URL: ${APP_PUBLIC_BASE_URL:-} YYD_NOTIFICATION_CENTER_URL: ${YYD_NOTIFICATION_CENTER_URL:-} YYD_NOTIFICATION_PROJECT_CODE: ${YYD_NOTIFICATION_PROJECT_CODE:-fixed_asset} YYD_NOTIFICATION_PROJECT_SECRET: ${YYD_NOTIFICATION_PROJECT_SECRET:-} YYD_NOTIFICATION_SEND_ENABLED: ${YYD_NOTIFICATION_SEND_ENABLED:-false} YYD_NOTIFICATION_SEND_TEST_USER_IDS: ${YYD_NOTIFICATION_SEND_TEST_USER_IDS:-} YYD_NOTIFICATION_SEND_FULL_ROLLOUT: ${YYD_NOTIFICATION_SEND_FULL_ROLLOUT:-false} YYD_NOTIFICATION_LOGIN_ENABLED: ${YYD_NOTIFICATION_LOGIN_ENABLED:-false} YYD_NOTIFICATION_LOGIN_TEST_USER_IDS: ${YYD_NOTIFICATION_LOGIN_TEST_USER_IDS:-} YYD_NOTIFICATION_LOGIN_FULL_ROLLOUT: ${YYD_NOTIFICATION_LOGIN_FULL_ROLLOUT:-false} DOWNLOADS_DIR: /app/downloads depends_on: mysql: condition: service_healthy volumes: - backend_uploads:/app/uploads - ./frontend/public/branding:/app/branding:ro - ./downloads:/app/downloads:ro # 前端服务 frontend: build: context: ./frontend dockerfile: Dockerfile args: VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api} VITE_AUTH_MODE: ${AUTH_MODE:-local} VITE_KEYCLOAK_URL: ${KEYCLOAK_URL:-} VITE_KEYCLOAK_REALM: ${KEYCLOAK_REALM:-} VITE_KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID:-} container_name: equipment-frontend restart: always ports: - "80:80" - "443:443" depends_on: - backend volumes: - /etc/letsencrypt:/etc/letsencrypt:ro - ./certbot/www:/var/www/certbot - ./frontend/public/branding:/usr/share/nginx/html/branding:ro volumes: mysql_data: backend_uploads: