version: '3.8' services: # Flask API Backend spawner: build: . container_name: spawner restart: unless-stopped ports: - "5000:5000" # Optional: Direktzugriff für Debugging volumes: # .env zur Laufzeit laden (wird bei restart neu gelesen!) - .env:/app/.env:ro # Docker-Socket für Container-Management - /var/run/docker.sock:/var/run/docker.sock:rw # Persistente Daten - ./data:/app/data # Logs - ./logs:/app/logs # .env wird als Volume gemountet - keine Duplication nötig! networks: - web labels: # Traefik aktivieren - "traefik.enable=true" - "traefik.docker.network=web" # API-Router (hoehere Prioritaet fuer /api/*) - "traefik.http.routers.spawner-api.rule=Host(`${SPAWNER_SUBDOMAIN:-coder}.${BASE_DOMAIN}`) && PathPrefix(`/api`)" - "traefik.http.routers.spawner-api.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}" - "traefik.http.routers.spawner-api.tls.certresolver=${TRAEFIK_CERTRESOLVER:-lets-encrypt}" - "traefik.http.routers.spawner-api.priority=200" - "traefik.http.routers.spawner-api.service=spawner-api-service" - "traefik.http.services.spawner-api-service.loadbalancer.server.port=5000" # Health-Router (nur fuer /health Endpoint) - "traefik.http.routers.spawner-health.rule=Host(`${SPAWNER_SUBDOMAIN:-coder}.${BASE_DOMAIN}`) && PathPrefix(`/health`)" - "traefik.http.routers.spawner-health.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}" - "traefik.http.routers.spawner-health.tls.certresolver=${TRAEFIK_CERTRESOLVER:-lets-encrypt}" - "traefik.http.routers.spawner-health.priority=100" - "traefik.http.routers.spawner-health.service=spawner-api-service" # Metadata - "spawner.managed=true" - "spawner.version=2.0.0" - "spawner.type=api-service" # Health-Check healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s # Next.js Frontend frontend: build: ./frontend container_name: spawner-frontend restart: unless-stopped environment: - NEXT_PUBLIC_API_URL= networks: - web labels: # Traefik aktivieren - "traefik.enable=true" - "traefik.docker.network=web" # Frontend-Router (niedrigere Prioritaet - Catch-All) - "traefik.http.routers.spawner-frontend.rule=Host(`${SPAWNER_SUBDOMAIN:-coder}.${BASE_DOMAIN}`)" - "traefik.http.routers.spawner-frontend.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}" - "traefik.http.routers.spawner-frontend.tls.certresolver=${TRAEFIK_CERTRESOLVER:-lets-encrypt}" - "traefik.http.routers.spawner-frontend.priority=50" - "traefik.http.routers.spawner-frontend.service=spawner-frontend-service" - "traefik.http.services.spawner-frontend-service.loadbalancer.server.port=3000" # Metadata - "spawner.managed=true" - "spawner.version=2.0.0" - "spawner.type=frontend-service" # Health-Check healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/"] interval: 30s timeout: 10s retries: 3 start_period: 30s depends_on: - spawner # Externes Netzwerk (von deinem Traefik bereits vorhanden) networks: web: external: true