services: mysql: image: mysql:8.4 container_name: shoe-swapper-mysql restart: unless-stopped environment: MYSQL_DATABASE: ${MYSQL_DATABASE:-shoe_swapper} MYSQL_USER: ${MYSQL_USER:-shoe} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-change-me-db-password} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-change-me-root-password} TZ: ${TZ:-Asia/Shanghai} command: [ "--character-set-server=utf8mb4", "--collation-server=utf8mb4_0900_ai_ci" ] volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_ROOT_PASSWORD:-change-me-root-password}"] interval: 5s timeout: 5s retries: 30 app: build: context: . dockerfile: Dockerfile container_name: shoe-swapper-app restart: unless-stopped depends_on: mysql: condition: service_healthy env_file: - .env.production environment: NODE_ENV: production PORT: 3000 DATABASE_URL: mysql://${MYSQL_USER:-shoe}:${MYSQL_PASSWORD:-change-me-db-password}@mysql:3306/${MYSQL_DATABASE:-shoe_swapper} TZ: ${TZ:-Asia/Shanghai} volumes: - app_tmp:/app/.tmp ports: - "3000:3000" nginx: image: nginx:1.27-alpine container_name: shoe-swapper-nginx restart: unless-stopped depends_on: - app ports: - "80:80" volumes: - ./deploy/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro volumes: mysql_data: app_tmp: