2 UI Container
muke edited this page 2026-03-02 23:09:57 +01:00

UI-Container - Architektur & Betrieb

Übersicht

Der PhorgeRunner UI-Container ist ein separater Service für die Weboberfläche, der parallel zum CLI-Container läuft. Er basiert auf nginx + PHP-FPM und dient der Anzeige von Logs, Runs und Status-Informationen.

Architektur

Stack

  • Base-Image: php:8.2-fpm
  • Webserver: nginx
  • PHP-Runtime: PHP-FPM (FastCGI Process Manager)
  • DocumentRoot: /app/public

PHP-Extensions

  • pdo - Datenbank-Abstraktion
  • pdo_mysql - MySQL-Treiber
  • mbstring - Multibyte-String-Funktionen
  • intl - Internationalisierung
  • zip - ZIP-Archiv-Handling

Netzwerk

  • Interner Port: 80
  • Externer Port: Konfigurierbar über UI_PORT in .env (Default: 8080)
  • DB-Zugriff: Über MySQL-Service im Docker-Network

UI-Assets & Frontend-Bibliotheken

Der UI-Container nutzt moderne, leichtgewichtige Frontend-Bibliotheken:

Pico.css (v2.0.6)

  • Zweck: Minimalistisches, klassenfreies CSS-Framework
  • Lizenz: MIT
  • CDN: jsDelivr
  • Features: Responsive Design, Dark Mode, Form-Styling
  • Größe: ~80 KB minifiziert

Lucide Icons (v0.17.5)

  • Zweck: SVG-Icon-Bibliothek für UI-Elemente
  • Lizenz: ISC
  • CDN: jsDelivr (lucide-static)
  • Integration: Inline-SVG via IconHelper PHP-Klasse
  • Icons: Manifest-gesteuert (12 Icons: home, settings, log-out, list, check-circle, alert-circle, info, x-circle, activity, database, server, terminal)

Asset-Management

Download während Build:

scripts/download-assets.sh
  • Läuft automatisch beim Docker-Build
  • Lädt Pico.css und ausgewählte Icons von CDN
  • Speichert in public/assets/css/ und public/assets/icons/

IconHelper PHP-Klasse:

use App\UI\IconHelper;

// Inline SVG rendern
IconHelper::render('home', 'my-icon-class');

// Icon-URL für <img>
IconHelper::url('settings');

// Icon-Verfügbarkeit prüfen
IconHelper::exists('database');

// Alle verfügbaren Icons
IconHelper::available();

Manifest-Konfiguration:
config/assets/icons-manifest.json definiert, welche Icons heruntergeladen werden.

Lizenz-Compliance:
Alle Asset-Lizenzen sind dokumentiert in public/assets/LICENSE.md.

Dateien & Konfiguration

Dockerfile.ui

Baut das UI-Container-Image mit nginx und PHP-FPM.

Wichtige Schritte:

  1. Installiert nginx und PHP-Extensions
  2. Erstellt non-root User phorgerunner
  3. Kopiert nginx- und PHP-FPM-Konfigurationen
  4. Kopiert Anwendungscode (read-only)
  5. Setzt Entrypoint

nginx-Konfiguration

config/nginx/nginx.conf

  • Haupt-nginx-Konfiguration
  • Logs gehen nach stdout/stderr für Container-Visibility
  • Performance-Tuning (Gzip, Keepalive, Worker)

config/nginx/default.conf

  • VHost-Konfiguration für die UI
  • DocumentRoot: /app/public
  • PHP-Verarbeitung via FastCGI zu Unix-Socket
  • Security: Deny-Rules für sensitive Verzeichnisse (/config, /logs, /sql, /tests)
  • Static-Asset-Caching

PHP-FPM-Konfiguration

config/php-fpm/www.conf

  • Pool-Konfiguration für PHP-FPM
  • User: phorgerunner, Group: www-data
  • Unix-Socket: /run/php/php-fpm.sock
  • Process-Management: Dynamic (2-10 Worker)
  • Memory-Limit: 256MB
  • Logs nach stdout/stderr

Entrypoint

docker-entrypoint-ui.sh

  • Erstellt benötigte Verzeichnisse (/run/php, /var/log/nginx)
  • Generiert config.php aus Umgebungsvariablen (falls nicht vorhanden)
  • Testet nginx-Konfiguration
  • Startet PHP-FPM im Hintergrund
  • Startet nginx im Vordergrund

Docker-Compose-Integration

Der UI-Service ist in allen Compose-Dateien integriert:

docker-compose.dev.yml (Development)

ui:
  build:
    context: .
    dockerfile: Dockerfile.ui
  volumes:
    - ./:/app:delegated  # Source-Mount für Live-Entwicklung
  ports:
    - "${UI_PORT:-8080}:80"
  depends_on:
    - mysql

docker-compose.yml (Production Build)

ui:
  image: phorgerunner-ui:prod
  build:
    context: .
    dockerfile: Dockerfile.ui
  ports:
    - "${UI_PORT:-8080}:80"

docker-compose.prod.yml (Production Deployment)

ui:
  image: ${REGISTRY}/phorgerunner-ui:${TAG}
  volumes:
    - /var/lib/phorgerunner/logs:/app/logs:rw
    - /etc/phorgerunner/config:/app/config:ro
  ports:
    - "${UI_PORT:-8080}:80"

Umgebungsvariablen

Development (.env)

UI_PORT=8080
DB_HOST=mysql
DB_PORT=3306
MYSQL_DATABASE=phorgerunner
MYSQL_USER=phorgerunner
MYSQL_PASSWORD=secret

Production

Zusätzlich:

REGISTRY=registry.example.org
TAG=1.0.0
LOG_MODE=file
LOG_FILE_PREFIX=ui

Health-Check

Der UI-Container hat einen HTTP-Healthcheck:

healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"]
  interval: 30s
  timeout: 5s
  retries: 3

Betrieb

Development-Start

# Container bauen
docker compose -f docker-compose.dev.yml build ui

# Container starten
docker compose -f docker-compose.dev.yml up ui

# UI aufrufen
http://localhost:8080

Production-Build

# Image bauen
docker compose -f docker-compose.yml build ui

# Als Release taggen
docker tag phorgerunner-ui:prod registry.example.org/phorgerunner-ui:1.0.0

# Pushen
docker push registry.example.org/phorgerunner-ui:1.0.0

Logs anzeigen

# Alle Logs
docker compose logs ui

# Live-Logs folgen
docker compose logs -f ui

# Nur nginx-Logs
docker compose exec ui tail -f /var/log/nginx/access.log

# PHP-FPM-Logs
docker compose logs ui | grep php-fpm

In Container einsteigen

# Shell im laufenden Container
docker compose exec ui /bin/bash

# nginx-Config testen
docker compose exec ui nginx -t

# PHP-FPM-Status
docker compose exec ui php-fpm -t

Ordnerstruktur

/app/
├── public/              # DocumentRoot (nginx)
│   ├── index.php       # UI-Einstiegspunkt
│   └── assets/         # CSS, JS, Icons (zukünftig)
├── src/                # PHP-Klassen (read-only)
├── config/             # App-Konfiguration
│   ├── nginx/         # nginx-Configs (Container-Level)
│   └── php-fpm/       # PHP-FPM-Configs (Container-Level)
└── logs/               # Anwendungs-Logs

Security

Zugriffsschutz

  • nginx blockt Zugriff auf sensitive Verzeichnisse (/config, /logs, /sql, /tests)
  • Container läuft als non-root User (phorgerunner:www-data)
  • Config-Dateien sind nur lesbar für Owner

Geplante Erweiterungen

  • HTTP-Basic-Auth für UI-Zugriff (T1043)
  • Read-only DB-User für UI-Zugriffe
  • TLS-Termination im Reverse-Proxy

Nächste Schritte

Die UI-Container-Basis ist fertig. Folgende Schritte sind offen:

  1. T1043 - Reverse-Proxy/Routing zum UI (HTTPS, Auth)
  2. T1045 - Pico.css Integration
  3. T1046 - Lucide Icons Integration
  4. T1044 - UI-Layout & Navigation
  5. T1048 - Datenanbindung (Read-only)
  6. T1049 - UI-Seiten v1

Test-Seite

Die Test-Seite unter public/index.php zeigt:

  • PHP-Version & Server-Info
  • Autoloader-Status
  • Konfigurationsdatei-Status
  • Datenbank-Verbindung (wenn config vorhanden)
  • Geladene PHP-Extensions

Troubleshooting

Container startet nicht

# Build-Logs prüfen
docker compose -f docker-compose.dev.yml build ui --no-cache

# nginx-Config testen
docker compose exec ui nginx -t

# PHP-FPM testen
docker compose exec ui php-fpm -t

Seite lädt nicht

# nginx-Logs prüfen
docker compose logs ui | grep nginx

# PHP-Fehler prüfen
docker compose logs ui | grep PHP

# In Container einsteigen
docker compose exec ui /bin/bash

Datenbank nicht erreichbar

# MySQL-Service prüfen
docker compose ps mysql

# Netzwerk-Verbindung testen
docker compose exec ui ping mysql

# DB-Zugriff testen
docker compose exec ui php -r "new PDO('mysql:host=mysql', 'root', 'password');"

Definition of Done (T1041 & T1042)

T1041 - UI-Service als dritter Container

  • Docker-Compose enthält neuen Service "ui"
  • UI-Container greift auf denselben Code-Stand zu (read-only möglich)
  • Interne Netzwerkverbindung zur MySQL-Instanz funktioniert
  • UI ist über definierten Port erreichbar (via UI_PORT)
  • Container startet ohne Fehler

T1042 - Webserver-Stack im UI-Container

  • Base-Image festgelegt (php:8.2-fpm + nginx)
  • DocumentRoot zeigt auf public/
  • Access- und Error-Logs gehen nach stdout/stderr
  • Standard-VHost ist konfiguriert
  • Container startet ohne Konfigurationswarnungen