spawner/docs/install/DEPLOYMENT_GUIDE.md
XPS\Micro 10b28179fc feat: implement dynamic template system with auto-detection
**Backend (config.py):**
- Add dynamic template loading from USER_TEMPLATE_IMAGES (.env)
- Add template metadata loading from templates.json
- Implement automatic type extraction from image names
- Remove hardcoded template definitions (dev/prod)
- Maintain legacy USER_TEMPLATE_IMAGE for backward compatibility

**Configuration:**
- Add templates.json with metadata for template-01, template-02, template-next
- Update .env.example with new USER_TEMPLATE_IMAGES variable (semicolon-separated)
- Document automatic template type extraction

**Installation (install.sh):**
- Implement auto-detection for all user-template-* directories
- Replace hardcoded template builds with dynamic loop
- Calculate TOTAL_BUILDS dynamically
- Add special handling for Next.js templates

**Documentation:**
- Move MVP_DEPLOYMENT_GUIDE.md to docs/install/DEPLOYMENT_GUIDE.md
- Add "Dynamic Template System" section to CLAUDE.md
- Update docs/install/README.md with Quick Links and dynamic system info
- Add references to deployment guide in CLAUDE.md

**Templates:**
- Reorganize user-template/ → user-template-01/ (Nginx Basic)
- Add user-template-02/ (Nginx Advanced)
- Keep user-template-next/ unchanged

**Benefits:**
- Unlimited number of templates (no longer hardcoded to 2)
- Metadata-driven display in dashboard
- Automatic image discovery and building
- Extensible without code changes

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-01 09:04:59 +01:00

13 KiB

Container Spawner - Deployment Guide

🎯 Überblick

Das System unterstützt beliebig viele User-Templates über ein dynamisches Konfigurationssystem:

  • Templates werden in .env definiert (semikolon-getrennt)
  • Metadaten (Namen, Beschreibungen) kommen aus templates.json
  • install.sh baut automatisch alle user-template-* Verzeichnisse
  • Jeder Benutzer kann beliebig viele Container verschiedener Typen erstellen

Standardtemplates (können beliebig erweitert werden):

  • template-01: Nginx Basic - Einfacher Nginx-Server mit statischen Dateien
  • template-02: Nginx Advanced - Nginx mit erweiterten Features
  • template-next: Next.js Production - React-App mit Shadcn/UI

📋 Voraussetzungen

  • Docker & Docker Compose
  • Python 3.11+
  • Node.js 18+ (für Frontend)
  • Traefik als Reverse Proxy mit Docker Provider

🚀 Deployment-Anleitung

Phase 1: Vorbereitung (15 Minuten)

1.1 Code auschecken

git pull origin main

1.2 Alte Daten bereinigen (CLEAN SLATE)

# Alle alten User-Container stoppen
docker ps -a | grep "user-" | awk '{print $1}' | xargs docker rm -f 2>/dev/null || true

# Alte Datenbank löschen
rm -f spawner.db

# Logs löschen
rm -rf logs/*

1.3 Templates werden automatisch gebaut!

# install.sh erkennt AUTOMATISCH alle user-template-* Verzeichnisse und baut sie:
# - user-template-01/
# - user-template-02/
# - user-template-next/
# etc.

# Überprüfung der verfügbaren Template-Verzeichnisse:
ls -d user-template*

# Expected output:
# user-template-01  user-template-02  user-template-next

WICHTIG: Das install.sh-Script baut automatisch alle Templates - keine manuellen Docker-Builds nötig!

1.4 Environment konfigurieren

# Copy beispiel Datei
cp .env.example .env

# Bearbeite .env und passe an:
nano .env

Erforderliche Änderungen in .env:

# Pflichtfelder
SECRET_KEY=<generiert mit: python3 -c "import secrets; print(secrets.token_hex(32))">
BASE_DOMAIN=yourdomain.com
SPAWNER_SUBDOMAIN=coder
TRAEFIK_NETWORK=web
TRAEFIK_CERTRESOLVER=lets-encrypt
TRAEFIK_ENTRYPOINT=websecure

# Dynamische Template-Konfiguration (Semikolon-getrennt)
# Liste aller verfügbaren Container-Images
# Metadaten (Namen, Beschreibungen) werden aus templates.json geladen
USER_TEMPLATE_IMAGES=user-template-01:latest;user-template-02:latest;user-template-next:latest

# Optional: SMTP für Magic Links
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=noreply@example.com
SMTP_PASSWORD=password
SMTP_FROM=noreply@example.com
FRONTEND_URL=https://coder.yourdomain.com

Hinweis: Behalte alle anderen Einstellungen aus .env.example (CORS, JWT, etc.)

Phase 2: Services starten (10 Minuten)

2.1 Docker Compose starten

docker-compose up -d --build

# Warte bis Services bereit sind
sleep 10

# Überprüfe Status
docker-compose ps

Erwartet Output:

NAME                STATUS              PORTS
spawner             Up X seconds        5000/tcp
frontend            Up X seconds        3000/tcp
traefik             Up X seconds        80/tcp, 443/tcp, 8080/tcp

2.2 Logs prüfen

# Backend Logs
docker-compose logs spawner | tail -20

# Frontend Logs
docker-compose logs frontend | tail -20

# Traefik Logs
docker-compose logs traefik | tail -20

Wichtig: Suche nach ERROR-Meldungen. Häufige Fehler:

  • docker.errors.ImageNotFound: Template-Images nicht gebaut
  • ConnectionRefusedError: Backend nicht erreichbar
  • CORS error: CORS_ORIGINS nicht konfiguriert

2.3 Health Check

# Backend Health
curl -s http://localhost:5000/health | jq .

# Frontend (falls lokal erreichbar)
curl -s http://localhost:3000 | head -20

Phase 3: Erste Registrierung (5 Minuten)

3.1 Öffne Dashboard

https://coder.yourdomain.com

3.2 Registrierung

  1. Klick auf "Registrieren"
  2. Gib Email-Adresse ein: test@yourdomain.com
  3. Klick "Magic Link senden"
  4. Überprüfe Email (oder Logs für Magic Link Token wenn SMTP nicht konfiguriert)
  5. Klick auf Magic Link in Email
  6. Du wirst zum Dashboard weitergeleitet

3.3 Dashboard überprüfen

  • N Container-Cards sichtbar (entsprechend USER_TEMPLATE_IMAGES)
    • Standardmäßig: template-01, template-02, template-next
  • Alle haben Status "Noch nicht erstellt"
  • Jede Card zeigt Display-Namen und Beschreibung aus templates.json
  • Buttons zeigen "Erstellen & Öffnen"

Phase 4: Teste beide Container (10 Minuten)

4.1 Development Container erstellen

Dashboard: Dev Container Card → Click "Erstellen & Öffnen"

Erwartet:
1. Loading-Spinner erscheint
2. Neuer Browser-Tab öffnet sich
3. URL: https://coder.yourdomain.com/test-dev (mit deinem slug)
4. Nginx-Willkommensseite wird angezeigt

4.2 Dashboard aktualisieren

Zurück zum Spawner-Tab

Erwartet:
1. Dev-Container Status = "Läuft"
2. Button ändert sich zu "Service öffnen"
3. Last-Used Timestamp wird angezeigt

4.3 Production Container erstellen

Dashboard: Prod Container Card → Click "Erstellen & Öffnen"

Erwartet:
1. Loading-Spinner erscheint
2. Neuer Browser-Tab öffnet sich
3. URL: https://coder.yourdomain.com/test-prod (mit deinem slug)
4. Next.js Demo-Seite mit Shadcn/UI wird angezeigt

4.4 Beide Containers öffnen

Dashboard: Click "Service öffnen" für Dev-Container
→ Öffnet Dev-Container in bestehendem/neuem Tab

Dashboard: Click "Service öffnen" für Prod-Container
→ Öffnet Prod-Container in bestehendem/neuem Tab

Beide sollten funktionieren, ohne /dev oder /prod in der URL!

🔍 Verification Checklist

Backend

  • spawner Container läuft (docker ps | grep spawner)
  • Flask Server startet ohne Fehler (docker-compose logs spawner | grep "Running on")
  • UserContainer Tabelle existiert (docker exec spawner sqlite3 /app/data/users.db ".schema user_container")
  • GET /api/user/containers gibt 2 Containers zurück (mit Status "not_created")
  • POST /api/container/launch/dev funktioniert und erstellt Container

Frontend

  • Dashboard lädt beide Container-Cards
  • API-Calls funktionieren (Browser DevTools → Network Tab)
  • Buttons sind nicht disabled
  • Loading State erscheint beim Klick
  • URLs öffnen sich in neuem Tab

Docker & Traefik

  • docker ps | grep user- zeigt 2 Container nach Launch
  • Traefik Dashboard zeigt 2 HTTP Routers (für dev und prod)
  • StripPrefix entfernt /{slug}-{type} korrekt
  • Beide Containers sind erreichbar ohne /dev oder /prod in der URL

URLs

  • https://coder.yourdomain.com/{slug}-dev → Dev-Container
  • https://coder.yourdomain.com/{slug}-prod → Prod-Container
  • Keine 404 oder CORS-Fehler in Browser Console

🐛 Troubleshooting

Problem: Container spawnt nicht

Symptom: Klick auf "Erstellen & Öffnen" → Fehler "Container konnte nicht erstellt werden"

Lösung:

# 1. Überprüfe Logs
docker-compose logs spawner | tail -50

# 2. Überprüfe ob Images existieren
docker images | grep user-

# 3. Falls nicht vorhanden, baue neu:
docker build -t user-service-template:latest user-template/
docker build -t user-template-next:latest user-template-next/

# 4. Starte Services neu
docker-compose restart spawner

Problem: URL öffnet nicht / 404 Error

Symptom: Browser zeigt 404 oder Timeout beim Klick "Service öffnen"

Lösung:

# 1. Überprüfe Container läuft
docker ps | grep user-testuser-dev

# 2. Überprüfe Traefik Dashboard
curl http://localhost:8080/api/http/routers | grep user

# 3. Überprüfe Container-Labels
docker inspect user-testuser-dev-1 | grep -A5 "traefik"

# 4. Falls Labels falsch, starte Services neu
docker-compose restart

# 5. Überprüfe Traefik Logs
docker-compose logs traefik | grep user

Problem: StripPrefix funktioniert nicht

Symptom: Container erhält Path mit /{slug}-dev noch darin

Lösung:

# 1. Prüfe Traefik Middleware
curl http://localhost:8080/api/http/middlewares | jq . | grep -A10 "user"

# 2. Container sollte bei / landen, nicht bei /{slug}-dev
curl -H "Host: coder.yourdomain.com" \
  "http://localhost:8080/testuser-dev/this/is/a/test"
# Sollte zu Container weitergeleitet werden mit Path: /this/is/a/test

# 3. Falls Problem persistiert, rebuild Traefik
docker-compose down
docker-compose up -d --build traefik

Symptom: Email wird nicht empfangen oder Link funktioniert nicht

Lösung:

# 1. Überprüfe SMTP Konfiguration
docker-compose logs spawner | grep -i smtp

# 2. Falls SMTP nicht konfiguriert, überprüfe Logs für Token
docker-compose logs spawner | grep "Magic Link" | tail -5

# 3. Kopiere Token manuell aus Logs und öffne URL:
# https://coder.yourdomain.com/verify-signup?token=ABC123...

# 4. Zum Testen ohne SMTP:
# Setze SMTP_HOST=localhost im .env
# Tokens werden dann nur in Logs ausgegeben

Problem: Frontend kann nicht mit Backend kommunizieren

Symptom: CORS-Fehler oder "Netzwerkfehler"

Lösung:

# 1. Überprüfe CORS_ORIGINS in Backend
docker exec spawner grep CORS_ORIGINS /app/.env

# 2. Sollte enthalten: https://coder.yourdomain.com (oder http://localhost:3000 in Dev)

# 3. Falls nicht richtig gesetzt:
# Bearbeite .env und setze:
CORS_ORIGINS=https://coder.yourdomain.com

# 4. Restart Backend
docker-compose restart spawner

# 5. Browser Cache löschen und Seite neu laden

📊 Monitoring

Logs überwachen

# Alle Services
docker-compose logs -f

# Nur Backend
docker-compose logs -f spawner

# Traefik
docker-compose logs -f traefik

# Frontend
docker-compose logs -f frontend

Container Status

# Alle Container
docker ps

# Mit Filter
docker ps | grep user-

# Detailed Info
docker inspect user-testuser-dev-1

Traefik Status

# Routers
curl http://localhost:8080/api/http/routers

# Middlewares
curl http://localhost:8080/api/http/middlewares

# Services
curl http://localhost:8080/api/http/services

Datenbank prüfen

# Container-Liste
docker exec spawner sqlite3 /app/data/users.db \
  "SELECT id, user_id, container_type, container_id FROM user_container LIMIT 10;"

# User-Liste
docker exec spawner sqlite3 /app/data/users.db \
  "SELECT id, email, slug, state FROM user LIMIT 10;"

🔐 Security Checklist

  • SECRET_KEY ist generiert und komplex
  • JWT_SECRET_KEY ist gesetzt (oder nutzt SECRET_KEY)
  • CORS_ORIGINS ist auf richtige Domain gesetzt
  • SMTP_PASSWORD ist nicht im .env.example hart-codiert
  • Database-URL nutzt keine Standardpasswörter (für Production)
  • Traefik Let's Encrypt Email ist gesetzt
  • TLS ist aktiviert für alle Routes
  • Container-Ressource Limits sind gesetzt (Memory, CPU)

📈 Scaling & Performance

Single User Multiple Containers

  • Pro User können 2 Container laufen (dev und prod)
  • Jeder Container: 512MB RAM, 0.5 CPU (konfigurierbar)
  • Für 100 User: Max 1GB RAM pro Container = 200GB total (nicht realistisch!)

Production Empfehlungen

  • Datenbank: Wechsel auf PostgreSQL (in config.py kommentiert)
  • Storage: Persistente Volumes für Container-Daten
  • Backups: Regelmäßige Backups der Datenbank und User-Volumes
  • Monitoring: Prometheus + Grafana für Metrics
  • Logging: Centralized Logging (ELK, Loki)

Load Testing

# Einfacher Test mit 10 gleichzeitigen Containern
for i in {1..10}; do
  docker run -d \
    --network web \
    --label "test=true" \
    user-service-template:latest
done

# Überwachen
docker stats | grep "test"

# Cleanup
docker ps --filter "label=test=true" | xargs docker rm -f

🎓 Nächste Schritte

Phase 1: MVP Live

  • 2 Container-Typen (dev, prod)
  • On-Demand Erstellung
  • Multi-Container Dashboard
  • Status-Tracking

Phase 2: Enhancements (Optional)

  • Container-Logs im Dashboard
  • Container-Restart pro Type
  • Resource-Monitoring
  • Container-Cleanup (Idle Timeout)
  • Custom Templates vom User

Phase 3: Admin Features (Optional)

  • Container-Management im Admin-Panel
  • User-Quotas pro Container-Typ
  • Template-Updates ohne Service-Restart
  • Audit Logging für Container-Events

📞 Support & Dokumentation

Wichtige Dateien

  • IMPLEMENTATION_SUMMARY.md - Detaillierte Feature-Liste
  • TEST_VERIFICATION.md - Test-Anleitung
  • CLAUDE.md - Projekt-Übersicht
  • docker-compose.yml - Service-Konfiguration
  • .env.example - Environment-Template

Häufig benötigte Commands

# Status überprüfen
docker-compose ps

# Logs anschauen
docker-compose logs -f [service]

# Services neu starten
docker-compose restart [service]

# Container in Python Shell bearbeiten
docker exec -it spawner python

# Datenbank migrieren
docker exec spawner flask db migrate
docker exec spawner flask db upgrade

# Admin-User erstellen
docker exec -it spawner python <<EOF
from app import app, db
from models import User
with app.app_context():
    user = User(email='admin@example.com', slug='admin')
    user.is_admin = True
    user.state = 'verified'
    db.session.add(user)
    db.session.commit()
EOF

Version: 1.0.0 (MVP) Deployment Date: 2025-01-31 Last Updated: 2025-02-01 Status: Ready for Production