# Server-Stack: gebauter Stand, keine Quellcode-Mounts, keine Datei-Watcher. # docker compose up --build --detach # # Fuer die Entwicklung mit Hot Reload compose.dev.yaml verwenden. name: leistungsbilanz x-build: &build context: . target: prod args: # Wird von next build in .next/routes-manifest.json eingebacken, siehe # Dockerfile. Muss der API-Adresse in diesem Netz entsprechen. API_INTERNAL_URL: http://api:3000 x-service-defaults: &service-defaults init: true restart: unless-stopped # Der API-Prozess beendet HTTP-Server und SQLite-Handle auf SIGTERM; die # Frist gibt laufenden Requests Zeit, statt sie nach 10s in ein SIGKILL # laufen zu lassen. stop_grace_period: 20s # Das Image laeuft als "node" (UID 1000); zusaetzliche Rechte braucht # weder der API- noch der Web-Prozess. security_opt: - no-new-privileges:true cap_drop: - ALL logging: driver: json-file options: max-size: "20m" max-file: "10" services: api: <<: *service-defaults build: *build # "exec" beim letzten Schritt: sonst bleibt sh der Vordergrundprozess und # SIGTERM erreicht node nie. command: - sh - -c - node scripts/run-migrations.js && node scripts/db-verify-circuit-schema.js && exec node dist/server/index.js environment: NODE_ENV: production PORT: "3000" LOG_LEVEL: "${LOG_LEVEL:-info}" # Nicht auf dem Host veroeffentlicht: die API hat keine Authentifizierung # und wird ueber den Next.js-Rewrite im Web-Dienst erreicht. expose: - "3000" # Harte Obergrenze statt unbegrenztem Wachstum. memswap_limit == mem_limit # schaltet Swap fuer den Container ab, damit ein Leck den Container trifft # und nicht den Host. mem_limit: 512m memswap_limit: 512m volumes: - ./data:/app/data healthcheck: test: - CMD - node - -e - fetch('http://127.0.0.1:3000/health').then(response=>{if(!response.ok)process.exit(1)}).catch(()=>process.exit(1)) interval: 30s timeout: 3s retries: 5 start_period: 20s web: <<: *service-defaults build: *build command: - node_modules/.bin/next - start - -p - "3001" - --hostname - 0.0.0.0 environment: NODE_ENV: production API_INTERNAL_URL: http://api:3000 NEXT_TELEMETRY_DISABLED: "1" LOG_LEVEL: "${LOG_LEVEL:-info}" depends_on: api: condition: service_healthy ports: - "3001:3001" mem_limit: 1g memswap_limit: 1g healthcheck: # /web-health statt /health: next.config.mjs leitet /health an die API # weiter, und "/" wuerde wegen des Redirects auf /projects bei jeder # Probe zwei Seiten rendern. test: - CMD - node - -e - fetch('http://127.0.0.1:3001/web-health').then(response=>{if(!response.ok)process.exit(1)}).catch(()=>process.exit(1)) interval: 30s timeout: 3s retries: 5 start_period: 20s