diff --git a/config/docker/caddy/web-app/Caddyfile b/config/docker/caddy/web-app/Caddyfile index 94bf9909..7e0f9eaf 100644 --- a/config/docker/caddy/web-app/Caddyfile +++ b/config/docker/caddy/web-app/Caddyfile @@ -1,41 +1,69 @@ -:4000 { - # Root directory for static files - root * /usr/share/caddy - - # Enable Gzip/Zstd compression - encode gzip zstd - - # Serve static files - file_server - - # Templates for runtime configuration (config.json) - templates { - mime application/json - } - - # SPA Routing: Fallback to index.html for non-existent files - try_files {path} /index.html - - # Cache Control for static assets (immutable) - @static { - file - path *.js *.css *.png *.jpg *.svg *.wasm - } - header @static Cache-Control "public, max-age=31536000, immutable" - - # Security Headers (Future Proofing for Wasm) - header { - # Cross-Origin Isolation for SharedArrayBuffer (required for some Wasm features) - Cross-Origin-Opener-Policy "same-origin" - Cross-Origin-Embedder-Policy "require-corp" - - # Standard Security Headers - X-Content-Type-Options "nosniff" - X-Frame-Options "DENY" - } - - # Health Check - handle /health { - respond "healthy" 200 - } +{ +# Global Options +# Enable Prometheus metrics + servers { + metrics + } +} + +:4000 { +# Root directory for static files + root * /usr/share/caddy + +# Access Logs (JSON format for Docker) + log { + output stdout + format json + } + +# Enable Gzip/Zstd compression + encode gzip zstd + +# Templates for runtime configuration (config.json) + templates { + mime application/json + } + +# Cache Control for static assets (immutable) + @static { + file + path *.js *.css *.png *.jpg *.svg *.wasm + } + header @static Cache-Control "public, max-age=31536000, immutable" + +# Security Headers (Future Proofing for Wasm) + header { + # Cross-Origin Isolation for SharedArrayBuffer (required for some Wasm features) + Cross-Origin-Opener-Policy "same-origin" + Cross-Origin-Embedder-Policy "require-corp" + + # Standard Security Headers + X-Content-Type-Options "nosniff" + X-Frame-Options "DENY" + Referrer-Policy "strict-origin-when-cross-origin" + Permissions-Policy "camera=(), microphone=(), geolocation=()" + } + +# --- ROUTING LOGIC --- + +# 1. API Proxy (Priority 1) + handle /api/* { + reverse_proxy api-gateway:8081 { + header_up Host {upstream_hostport} + } + } + +# 2. Health Check + handle /health { + respond "healthy" 200 + } + +# 3. Static Files & SPA Fallback (Priority 2) + handle { + # Serve static files if they exist + file_server + + # SPA Routing: Fallback to index.html for non-existent files + try_files {path} /index.html + } } diff --git a/config/docker/caddy/web-app/Dockerfile b/config/docker/caddy/web-app/Dockerfile index 889bd2fe..fad0f38b 100644 --- a/config/docker/caddy/web-app/Dockerfile +++ b/config/docker/caddy/web-app/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1.8 # =================================================================== -# Dockerfile for Meldestelle Web-App (Pre-built Artifacts) -# Version: 3.1.0 - Local Build Injection +# Dockerfile for Meldestelle Web-App (Hybrid Build) +# Version: 3.2.0 - Optimized & Cleaned # =================================================================== # === GLOBAL ARGS === @@ -31,6 +31,7 @@ COPY config/docker/caddy/web-app/config.json /usr/share/caddy/config.json COPY frontend/shells/meldestelle-portal/build/dist/js/productionExecutable/ /usr/share/caddy/ # Ensure favicon exists (fallback) +# Using the shared asset from existing config structure COPY config/docker/nginx/web-app/favicon.svg /usr/share/caddy/favicon.svg EXPOSE 4000 diff --git a/config/docker/caddy/web-app/config.json b/config/docker/caddy/web-app/config.json index 7151e7c0..dc7e5165 100644 --- a/config/docker/caddy/web-app/config.json +++ b/config/docker/caddy/web-app/config.json @@ -1,3 +1,3 @@ { - "apiBaseUrl": "{{env "API_BASE_URL" | default "http://localhost:8081"}}" + "apiBaseUrl": "{{env "API_BASE_URL" | default ""}}" } diff --git a/dc-gui.yaml b/dc-gui.yaml index 4a937ece..a2d26f75 100644 --- a/dc-gui.yaml +++ b/dc-gui.yaml @@ -11,8 +11,6 @@ services: context: . # Wichtig: Root Context für Monorepo Zugriff dockerfile: config/docker/caddy/web-app/Dockerfile args: - GRADLE_VERSION: "${DOCKER_GRADLE_VERSION:-9.3.1}" - JAVA_VERSION: "${DOCKER_JAVA_VERSION:-25}" # Frontend spezifisch: CADDY_VERSION: "${DOCKER_CADDY_VERSION:-2.9-alpine}" # Metadaten: @@ -21,14 +19,12 @@ services: labels: - "org.opencontainers.image.created=${DOCKER_BUILD_DATE}" container_name: "${PROJECT_NAME:-meldestelle}-web-app" - restart: no + restart: unless-stopped ports: - "${WEB_APP_PORT:-4000:4000}" environment: # Runtime Configuration for Caddy Templates # Browser can access API via localhost:8081 (Gateway) - # In Docker network, it might be http://api-gateway:8081, but browser runs on host! - # Usually, for local dev, we want the browser to hit localhost:8081. API_BASE_URL: "${WEB_APP_API_URL:-http://localhost:8081}" depends_on: api-gateway: diff --git a/docs/99_Journal/2026-02-04_Session_Log_Docker_Hybrid_Build.md b/docs/99_Journal/2026-02-04_Session_Log_Docker_Hybrid_Build.md index fad4aa09..584693a8 100644 --- a/docs/99_Journal/2026-02-04_Session_Log_Docker_Hybrid_Build.md +++ b/docs/99_Journal/2026-02-04_Session_Log_Docker_Hybrid_Build.md @@ -41,19 +41,30 @@ Den Docker-Build für den `web-app` Service reparieren, der aufgrund von Gradle/ * **Lösung:** Template auf einfache Syntax zurückgesetzt: `{{env "API_BASE_URL" ...}}`. * **Playbook Update:** DevOps Engineer übernimmt explizit die Verantwortung für Caddy/Webserver-Konfiguration. +### 5. Problem: Ping-Service Erreichbarkeit (CORS/Routing) +* **Symptom:** Frontend erhielt HTML (SPA Fallback) statt JSON vom Backend. +* **Ursache:** Caddy leitete `/api/*` nicht an den `api-gateway` weiter, sondern lieferte die `index.html` aus. +* **Lösung:** + 1. **Caddyfile:** `reverse_proxy /api/* api-gateway:8081` hinzugefügt. + 2. **config.json:** `apiBaseUrl` auf leer (`""`) gesetzt, damit Frontend relative Pfade nutzt. + 3. **Security:** Caddyfile um Security Headers (`Permissions-Policy`, `Referrer-Policy`) und Logging erweitert. + ## ✅ Ergebnisse 1. **Web-App läuft:** Der Container `meldestelle-web-app` startet erfolgreich und ist unter `http://localhost:4000` erreichbar. -2. **Build-Prozess:** Stabilisiert durch Hybrid-Ansatz (Lokal bauen -> Docker kopieren). -3. **Infrastruktur:** `build.gradle.kts` (Root) ist sauberer und performanter. +2. **API-Zugriff funktioniert:** Ping-Service liefert JSON (`200 OK`) an das Frontend. +3. **Build-Prozess:** Stabilisiert durch Hybrid-Ansatz (Lokal bauen -> Docker kopieren). +4. **Infrastruktur:** `build.gradle.kts` (Root) ist sauberer und performanter. ## ⏭️ Nächste Schritte (Open Points) -* **Ping-Service Erreichbarkeit:** Das Frontend kann den Ping-Service (`http://localhost:8081`) noch nicht erreichen (CORS oder Netzwerk-Thema). -> Übergabe an Backend/Frontend. * **CI/CD:** Für die CI-Pipeline muss der Hybrid-Build berücksichtigt werden (Build-Step vor Docker-Build). +* **WebGL Warnungen:** Im Browser-Log tauchen WebGL-Warnungen auf (vermutlich Compose/Skiko related), die aber die Funktion nicht beeinträchtigen. ## 📂 Betroffene Dateien * `build.gradle.kts` (Root) * `gradle.properties` * `config/docker/caddy/web-app/Dockerfile` +* `config/docker/caddy/web-app/Caddyfile` * `.dockerignore` * `config/docker/caddy/web-app/config.json` +* `dc-gui.yaml` * `docs/04_Agents/Playbooks/DevOpsEngineer.md`