services: api: build: context: ./api dockerfile: docker/Dockerfile volumes: - ./api:/app # Optional: echte status.txt aus der Produktion zum Testen einbinden, z.B. # - ./status.txt:/status.txt:ro working_dir: /app # Achtung: Eine Aenderung des Host-Ports muss in .env (MONITOR_API_BASE) nachgezogen # werden - das Frontend laeuft im Browser und erreicht die API nicht ueber das # Compose-Netzwerk, sondern ueber genau diesen Port. ports: - "8091:8080" environment: MONITOR_DB_PATH: /app/data/monitor.sqlite MONITOR_ADMIN_API_KEY: ${MONITOR_ADMIN_API_KEY:-dev-admin-key} MONITOR_STATUS_FILE: /status.txt MONITOR_DESK_COUNT: 8 MONITOR_SSE_MAX_ITERATIONS: 30 MONITOR_SSE_POLL_INTERVAL: 2 CODEBERG_API_BASE: https://codeberg.org/api/v1 CODEBERG_OWNER: ${CODEBERG_OWNER:-fds2610} CODEBERG_REPO: ${CODEBERG_REPO:-monitor} CODEBERG_TOKEN: ${CODEBERG_TOKEN:-} # Haelt Backlog/Done aus Codeberg aktuell (F4, siehe API.md Abschnitt "Codeberg-Sync"): # laeuft dasselbe Image wie api, teilt sich ueber das ./api-Volume dieselbe SQLite-Datei # und ruft bin/sync-codeberg.php in einer Endlosschleife auf. Ohne diesen Service bleibt # das Board leer, solange kein Agent selbst Tickets meldet. # Rein ausgehende Verbindungen (nach codeberg.org), kein Port-Mapping - in Produktion sind # also weder Proxy- noch Firewall-Freigaben noetig. sync: build: context: ./api dockerfile: docker/Dockerfile volumes: - ./api:/app working_dir: /app restart: unless-stopped depends_on: - api environment: MONITOR_DB_PATH: /app/data/monitor.sqlite MONITOR_SYNC_INTERVAL: ${MONITOR_SYNC_INTERVAL:-600} CODEBERG_API_BASE: https://codeberg.org/api/v1 CODEBERG_OWNER: ${CODEBERG_OWNER:-fds2610} CODEBERG_REPO: ${CODEBERG_REPO:-monitor} CODEBERG_TOKEN: ${CODEBERG_TOKEN:-} # "$$" ist ein maskiertes "$" - die Variable soll die Shell im Container aufloesen, nicht # Compose. Ein fehlgeschlagener Lauf (Codeberg nicht erreichbar, Rate-Limit) darf die # Schleife nicht beenden, sonst landet der Service in einer Restart-Schleife. command: - sh - -c - | while true; do php bin/sync-codeberg.php || echo "[sync] Lauf fehlgeschlagen, naechster Versuch in $${MONITOR_SYNC_INTERVAL}s" sleep "$$MONITOR_SYNC_INTERVAL" done # Statisches Frontend (html/) - Phase 2 der Neuausrichtung (Buero-Visualisierung). # Nur zur lokalen Ansicht/Entwicklung, kein Build-Schritt noetig (Vanilla HTML/CSS/JS). web: image: nginx:alpine volumes: - ./html:/usr/share/nginx/html:ro # Ueberlagert den Platzhalter html/API.md - der muss existieren, weil in # einem read-only gemounteten Verzeichnis kein Mountpoint angelegt werden kann. - ./API.md:/usr/share/nginx/html/API.md:ro # Setzt office.html als Einstiegsseite (sonst 403 auf der Basis-URL) und liefert # /config.js aus. Als Template gemountet, damit das nginx-Image beim Start # MONITOR_API_BASE per envsubst einsetzt (Ausgabe: /etc/nginx/conf.d/default.conf). - ./docker/nginx/default.conf.template:/etc/nginx/templates/default.conf.template:ro environment: # Wird in docker/nginx/default.conf.template eingesetzt und als /config.js an den # Browser ausgeliefert. Leer = gleicher Origin (relatives /api/v1). MONITOR_API_BASE: ${MONITOR_API_BASE:-} ports: - "8090:80" # Fuehrt die Node-basierten Frontend-Tests (tests/frontend/) aus. Node/npm sind nur im # Container noetig, nicht auf dem Host (analog zum api-Service mit PHP/Composer). frontend: image: node:20-alpine working_dir: /app volumes: - .:/app command: npm test