services: mysql: 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 - ./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 # Expose port only for debugging - remove in production # ports: # - "3306:3306" backend: build: context: ./backend dockerfile: Dockerfile 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:-http://localhost} - PORT=3001 volumes: - uploads_data:/app/uploads - ./upload:/app/legacy-uploads:ro 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 # Expose port only if not using reverse proxy ports: - "3001:3001" frontend: build: context: ./frontend dockerfile: Dockerfile args: - VITE_API_BASE_URL=${API_BASE_URL:-http://localhost:3001/api} container_name: rezepte-frontend-prod restart: unless-stopped ports: - "80:80" # Add port 443 if handling SSL directly in container # - "443:443" 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