version: '3.8' services: # Flask API Backend spawner: build: . container_name: spawner restart: unless-stopped env_file: - .env ports: - "5000:5000" # Optional: Direktzugriff für Debugging volumes: # Docker-Socket für Container-Management - /var/run/docker.sock:/var/run/docker.sock:rw # Persistente Daten - ./data:/app/data # Logs - ./logs:/app/logs environment: # Aus .env-Datei - Sicherheit - SECRET_KEY=${SECRET_KEY} - JWT_SECRET_KEY=${JWT_SECRET_KEY:-${SECRET_KEY}} # Domain & Routing - BASE_DOMAIN=${BASE_DOMAIN} - SPAWNER_SUBDOMAIN=${SPAWNER_SUBDOMAIN:-coder} - CORS_ORIGINS=https://${SPAWNER_SUBDOMAIN:-coder}.${BASE_DOMAIN},http://localhost:3000 # Docker & Traefik - TRAEFIK_NETWORK=${TRAEFIK_NETWORK} - DOCKER_HOST=${DOCKER_HOST:-unix:///var/run/docker.sock} # Templates (Dynamisches System) - USER_TEMPLATE_IMAGE=${USER_TEMPLATE_IMAGE:-user-template-01:latest} - USER_TEMPLATE_IMAGES=${USER_TEMPLATE_IMAGES:-"user-template-01:latest;user-template-02:latest;user-template-next:latest"} # Traefik-Zertifikate - TRAEFIK_CERTRESOLVER=${TRAEFIK_CERTRESOLVER:-lets-encrypt} - TRAEFIK_ENTRYPOINT=${TRAEFIK_ENTRYPOINT:-websecure} # SMTP & Email - SMTP_HOST=${SMTP_HOST} - SMTP_PORT=${SMTP_PORT} - SMTP_USER=${SMTP_USER} - SMTP_PASSWORD=${SMTP_PASSWORD} - SMTP_FROM=${SMTP_FROM} - SMTP_USE_TLS=${SMTP_USE_TLS:-true} - FRONTEND_URL=${FRONTEND_URL} # Magic Links - MAGIC_LINK_TOKEN_EXPIRY=${MAGIC_LINK_TOKEN_EXPIRY:-900} - MAGIC_LINK_RATE_LIMIT=${MAGIC_LINK_RATE_LIMIT:-3} # JWT - JWT_ACCESS_TOKEN_EXPIRES=${JWT_ACCESS_TOKEN_EXPIRES:-3600} # Ressourcen-Limits - DEFAULT_MEMORY_LIMIT=${DEFAULT_MEMORY_LIMIT:-512m} - DEFAULT_CPU_QUOTA=${DEFAULT_CPU_QUOTA:-50000} 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