services: backend: # Use pre-built image from registry instead of building image: docker.citysensor.de/rezepte-backend:latest container_name: rezepte-backend restart: unless-stopped environment: - NODE_ENV=production - DATABASE_URL=mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOST:-mysql}:${MYSQL_PORT:-3306}/rezepte - CORS_ORIGIN=https://rezepte.${DOMAIN} - PORT=3001 volumes: - uploads_data:/app/uploads # Legacy uploads can be mounted if needed # - ./legacy-uploads:/app/legacy-uploads:ro healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/api/health"] interval: 30s timeout: 10s retries: 3 labels: - "traefik.enable=true" # API Routes - "traefik.http.routers.backend.rule=Host(`rezepte.${DOMAIN}`) && PathPrefix(`/api`)" - "traefik.http.routers.backend.entrypoints=websecure" - "traefik.http.routers.backend.tls.certresolver=letsencrypt" - "traefik.http.services.backend.loadbalancer.server.port=3001" # Upload Routes - "traefik.http.routers.backend-uploads.rule=Host(`rezepte.${DOMAIN}`) && PathPrefix(`/uploads`)" - "traefik.http.routers.backend-uploads.entrypoints=websecure" - "traefik.http.routers.backend-uploads.tls.certresolver=letsencrypt" - "traefik.http.routers.backend-uploads.service=backend" networks: - traefik # Connect to external MySQL network - gitea_default frontend: # Use pre-built image from registry instead of building image: docker.citysensor.de/rezepte-frontend:latest container_name: rezepte-frontend restart: unless-stopped depends_on: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost/"] interval: 30s timeout: 10s retries: 3 labels: - "traefik.enable=true" # Frontend Routes (catch-all) - "traefik.http.routers.frontend.rule=Host(`rezepte.${DOMAIN}`)" - "traefik.http.routers.frontend.entrypoints=websecure" - "traefik.http.routers.frontend.tls.certresolver=letsencrypt" - "traefik.http.services.frontend.loadbalancer.server.port=80" # Lower priority than backend routes - "traefik.http.routers.frontend.priority=1" - "traefik.http.routers.backend.priority=10" - "traefik.http.routers.backend-uploads.priority=10" networks: - traefik phpmyadmin: image: phpmyadmin/phpmyadmin:latest container_name: rezepte-phpmyadmin restart: unless-stopped environment: - PMA_HOST=${MYSQL_HOST:-mysql} - PMA_PORT=${MYSQL_PORT:-3306} - PMA_USER=${MYSQL_ROOT_USER:-root} - PMA_PASSWORD=${MYSQL_ROOT_PASSWORD} - UPLOAD_LIMIT=2G - MEMORY_LIMIT=2G - MAX_EXECUTION_TIME=0 healthcheck: test: ["CMD", "curl", "-f", "http://localhost/"] interval: 30s timeout: 10s retries: 3 labels: - "traefik.enable=true" - "traefik.http.routers.phpmyadmin.rule=Host(`phpmyadmin.${DOMAIN}`)" - "traefik.http.routers.phpmyadmin.entrypoints=websecure" - "traefik.http.routers.phpmyadmin.tls.certresolver=letsencrypt" - "traefik.http.services.phpmyadmin.loadbalancer.server.port=80" # Optional: Add basic auth for extra security # - "traefik.http.routers.phpmyadmin.middlewares=auth" networks: - traefik # Connect to external MySQL network - gitea_default networks: traefik: external: true # Reference to external network (will be created by Gitea) # This network should already exist from your Gitea installation gitea_default: external: true volumes: uploads_data: driver: local