- Fix USER_TEMPLATE_IMAGES quoting in .env.example (prevent bash metacharacter issues) - Add all SMTP configuration variables to docker-compose environment - Add EMAIL service variables (FRONTEND_URL, MAGIC_LINK_EXPIRY, RATE_LIMIT) - Add JWT and resource limit variables - Improve environment variable organization with comments SMTP variables were defined in .env but not passed to container, causing email service configuration issues. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
139 lines
4.7 KiB
YAML
139 lines
4.7 KiB
YAML
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
|