services: mysql: # Production DB (no host port exposure by default) image: mysql:8.0 container_name: rezepte-mysql-prod restart: unless-stopped environment: MYSQL_DATABASE: rezepte MYSQL_USER: rezepte_user MYSQL_PASSWORD: ${MYSQL_PASSWORD:-change_this_password} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-change_this_root_password} volumes: - mysql_data:/var/lib/mysql # Optional initial import only for first deploy (remove afterwards) # - ./Rezepte.sql:/docker-entrypoint-initdb.d/01-rezepte.sql:ro # - ./ingredients.sql:/docker-entrypoint-initdb.d/02-ingredients.sql:ro # - ./Zubereitung.sql:/docker-entrypoint-initdb.d/03-zubereitung.sql:ro # - ./rezepte_bilder.sql:/docker-entrypoint-initdb.d/04-bilder.sql:ro healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10 networks: - rezepte-network backend: image: ${BACKEND_IMAGE:-ghcr.io/your-username/rezepte-backend:latest} container_name: rezepte-backend-prod restart: unless-stopped environment: NODE_ENV: production DATABASE_URL: mysql://rezepte_user:${MYSQL_PASSWORD:-change_this_password}@mysql:3306/rezepte JWT_SECRET: ${JWT_SECRET:-change_this_jwt_secret_min_32_characters} CORS_ORIGIN: ${CORS_ORIGIN:-https://rezepte.${DOMAIN}} PORT: 3001 volumes: - uploads_data:/app/uploads depends_on: mysql: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/api/health"] interval: 30s timeout: 10s retries: 3 networks: - rezepte-network frontend: image: ${FRONTEND_IMAGE:-ghcr.io/your-username/rezepte-frontend:latest} container_name: rezepte-frontend-prod restart: unless-stopped depends_on: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost/"] interval: 30s timeout: 10s retries: 3 networks: - rezepte-network volumes: mysql_data: driver: local uploads_data: driver: local networks: rezepte-network: driver: bridge