From 10bc690a03c22dd9fc1fe9e784e48f669f2b1a0f Mon Sep 17 00:00:00 2001 From: Tobias Sgoff Date: Thu, 15 Jan 2026 09:55:36 +0100 Subject: [PATCH] Add Docker setup and improve docker-compose --- DOCKER_README.md | 328 ++++++++++++++++++++++++++++++++++++++ Dockerfile | 65 ++++++++ docker-compose.yml | 77 ++++----- docker-entrypoint-init.sh | 175 ++++++++++++++++++++ 4 files changed, 601 insertions(+), 44 deletions(-) create mode 100644 DOCKER_README.md create mode 100644 Dockerfile create mode 100644 docker-entrypoint-init.sh diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 000000000..9eb2ca3db --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,328 @@ +# OpenXE Docker Setup mit Fork-Unterstützung + +Dieses Docker-Setup ermöglicht es, OpenXE einfach zu testen und zu entwickeln, einschließlich der Möglichkeit, verschiedene Forks und Branches zu verwenden. + +## Features + +- **Multi-Repository Support**: Teste jeden OpenXE Fork oder Branch +- **Automatische Datenbank-Initialisierung**: Nutzt das OpenXE Upgrade-System +- **Automatische Updates**: Führt Datenbank-Upgrades bei jedem Start aus +- **Persistente Daten**: Userdata bleibt zwischen Container-Neustarts erhalten + +## Voraussetzungen + +- Docker und Docker Compose installiert +- Mindestens 2GB freier RAM +- Ports 80 und 3306 verfügbar (oder in docker-compose.yml anpassen) + +## Schnellstart + +### 1. Original OpenXE Repository (Standard) + +```bash +cd /Users/sgo0002t/Desktop/openxe/OpenXE +docker-compose up -d +``` + +Dies verwendet den lokalen Code im aktuellen Verzeichnis. + +### 2. Einen Fork testen + +Um einen Fork zu testen, setze die Umgebungsvariablen `REPO_URL` und `BRANCH`: + +```bash +export REPO_URL=https://github.com/Avatarsia/OpenXE.git +export BRANCH=api-doc-2 +docker-compose up -d --build +``` + +**Wichtige Beispiele:** + +```bash +# Avatarsia Fork, Branch api-doc-2 +export REPO_URL=https://github.com/Avatarsia/OpenXE.git +export BRANCH=api-doc-2 + +# Original OpenXE Repository, main Branch +export REPO_URL=https://github.com/OpenXE-org/OpenXE.git +export BRANCH=main + +# Ein anderer Branch aus dem Original +export REPO_URL=https://github.com/OpenXE-org/OpenXE.git +export BRANCH=develop +``` + +### 3. Mit Beispieldaten + +Um Beispieldaten zu importieren: + +```bash +export IMPORT_SAMPLE=true +export REPO_URL=https://github.com/OpenXE-org/OpenXE.git +export BRANCH=main +docker-compose up -d --build +``` + +### 4. Mit eigenem Admin-Passwort + +Um ein eigenes Admin-Passwort zu setzen: + +```bash +export ADMIN_PASSWORD=MeinSicheresPasswort123 +export REPO_URL=https://github.com/OpenXE-org/OpenXE.git +export BRANCH=main +docker-compose up -d --build +``` + +Der Admin-User wird automatisch bei der ersten Initialisierung erstellt. + +## Umgebungsvariablen + +| Variable | Standard | Beschreibung | +|----------|---------|--------------| +| `REPO_URL` | `local` | Git Repository URL oder `local` für lokalen Code | +| `BRANCH` | `main` | Git Branch der ausgecheckt werden soll | +| `IMPORT_SAMPLE` | `false` | `true` um Beispieldaten zu importieren | +| `ADMIN_PASSWORD` | `openxe` | Passwort für den Admin-User | +| `DB_HOST` | `db` | MySQL/MariaDB Hostname | +| `DB_NAME` | `openxe` | Datenbank Name | +| `DB_USER` | `openxe` | Datenbank Benutzer | +| `DB_PASSWORD` | `openxe` | Datenbank Passwort | + +## Zugriff + +Nach dem Start ist OpenXE erreichbar unter: + +- **Web-Interface**: http://localhost + - **Login**: `admin` + - **Passwort**: `openxe` (oder der Wert von `ADMIN_PASSWORD`) + +- **MySQL**: localhost:3306 + - Benutzer: `openxe` + - Passwort: `openxe` + - Datenbank: `openxe` + +## Container verwalten + +### Status prüfen +```bash +docker-compose ps +``` + +### Logs anzeigen +```bash +# Alle Logs +docker-compose logs -f + +# Nur OpenXE App Logs +docker logs openxe-app -f + +# Nur Datenbank Logs +docker logs openxe-db -f +``` + +### Container stoppen +```bash +docker-compose down +``` + +### Container stoppen und Datenbank löschen +```bash +docker-compose down -v +``` + +### Neustart mit neuem Fork/Branch + +```bash +# Alte Container stoppen und Datenbank löschen +docker-compose down -v + +# Neuen Fork konfigurieren +export REPO_URL=https://github.com/IhrUsername/OpenXE.git +export BRANCH=ihr-branch + +# Neu starten +docker-compose up -d --build +``` + +## Entwicklungs-Workflow + +### Lokalen Code testen + +1. Klone das Repository: + ```bash + git clone https://github.com/OpenXE-org/OpenXE.git OpenXE + cd OpenXE + ``` + +2. Mache deine Änderungen im Code + +3. Starte mit lokalem Code: + ```bash + unset REPO_URL # oder export REPO_URL=local + docker-compose up -d --build + ``` + +4. Der Container verwendet nun deinen lokalen Code aus dem aktuellen Verzeichnis + +### Fork testen + +1. Setze Fork und Branch: + ```bash + export REPO_URL=https://github.com/Avatarsia/OpenXE.git + export BRANCH=api-doc-2 + ``` + +2. Starte Container: + ```bash + docker-compose down -v # Alte Daten löschen + docker-compose up -d --build + ``` + +3. Der Container klont automatisch den Fork beim Start + +### Zwischen Forks wechseln + +```bash +# Stoppe alte Container und lösche Datenbank +docker-compose down -v + +# Wechsle zu anderem Fork +export REPO_URL=https://github.com/anderer-user/OpenXE.git +export BRANCH=feature-xyz + +# Starte neu +docker-compose up -d --build +``` + +## Problembehandlung + +### Container startet nicht + +1. Logs prüfen: + ```bash + docker logs openxe-app + docker logs openxe-db + ``` + +2. Container stoppen und neu bauen: + ```bash + docker-compose down -v + docker-compose up -d --build + ``` + +### Datenbank-Fehler + +Wenn Datenbank-Fehler auftreten (z.B. fehlende Spalten): + +```bash +# Container stoppen und Datenbank löschen +docker-compose down -v + +# Neu starten - das Upgrade-System initialisiert die DB neu +docker-compose up -d +``` + +### Port bereits belegt + +Wenn Port 80 oder 3306 bereits belegt ist, passe die Ports in docker-compose.yml an: + +```yaml +services: + openxe: + ports: + - "8080:80" # OpenXE auf Port 8080 + + db: + ports: + - "3307:3306" # MySQL auf Port 3307 +``` + +### Upgrade-Probleme + +Falls das automatische Upgrade fehlschlägt, führe es manuell aus: + +```bash +docker exec -it openxe-app bash +cd /var/www/html/upgrade +php data/upgrade.php -db -do +exit +``` + +## Datenbank-Migration + +### Datenbank exportieren + +```bash +docker exec openxe-db mysqldump -u openxe -popenxe openxe > backup.sql +``` + +### Datenbank importieren + +```bash +docker exec -i openxe-db mysql -u openxe -popenxe openxe < backup.sql +``` + +## Architektur + +Das Setup besteht aus: + +- **Dockerfile**: Baut das OpenXE PHP/Apache Image + - PHP 8.1 mit allen benötigten Extensions + - Apache mit mod_rewrite + - Git für Repository-Klonen + +- **docker-compose.yml**: Orchestriert die Container + - OpenXE App Container + - MariaDB 10.11 Container + - Volumes für persistente Daten + +- **docker-entrypoint-init.sh**: Initialisierungs-Script + - Klont Repository wenn REPO_URL gesetzt ist + - Erstellt Datenbank-Konfiguration + - Führt OpenXE Upgrade-System aus + - Startet Apache + +## Persistente Daten + +- **./userdata**: OpenXE Benutzerdaten (gemounted) +- **dbdata (Volume)**: MariaDB Datenbank (Docker Volume) + +Die Datenbank bleibt zwischen Container-Neustarts erhalten, außer du löschst sie explizit mit `docker-compose down -v`. + +## Technische Details + +### Automatisches Upgrade + +Bei jedem Container-Start: +1. Prüft das Script, ob die Datenbank leer ist +2. Wenn leer: Führt `upgrade.php -db -do` aus (initialisiert Datenbank) +3. Wenn nicht leer: Führt trotzdem `upgrade.php -db -do` aus (für Updates) + +Dies stellt sicher, dass die Datenbank immer auf dem neuesten Stand ist. + +### Repository-Klonen + +Wenn `REPO_URL` auf einen Git-Repository-Link gesetzt ist: +1. Löscht alle Dateien außer `userdata` und `conf` +2. Klont das Repository in einen temporären Ordner +3. Kopiert alle Dateien (außer .git) nach `/var/www/html` +4. Setzt die Berechtigungen für www-data + +### Lokaler Code + +Wenn `REPO_URL=local` oder nicht gesetzt: +1. Verwendet den Code aus dem Build-Context (aktuelles Verzeichnis) +2. Kopiert ihn nach `/var/www/html` +3. Führt normale Initialisierung aus + +## Lizenz + +Dieses Docker-Setup ist Open Source. OpenXE selbst ist unter der EGPL 3.1 lizenziert. + +## Support + +Bei Problemen: +1. Prüfe die Logs: `docker logs openxe-app` +2. Prüfe die Container: `docker-compose ps` +3. Erstelle ein Issue im jeweiligen Repository diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..c2061fe3e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,65 @@ +FROM php:8.1-apache + +ARG BRANCH=main +ARG REPO_URL=local + +# Copy IMAP extension from mlocati/php-extension-installer image (pre-built) +COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/ + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + git \ + curl \ + libpng-dev \ + libonig-dev \ + libxml2-dev \ + libzip-dev \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libwebp-dev \ + libxpm-dev \ + libkrb5-dev \ + libldap2-dev \ + mariadb-client \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +# Install IMAP extension using php-extension-installer +RUN install-php-extensions imap + +# Configure PHP extensions +RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm \ + && docker-php-ext-configure ldap + +# Install PHP extensions +RUN docker-php-ext-install \ + pdo_mysql \ + mysqli \ + mbstring \ + exif \ + pcntl \ + bcmath \ + gd \ + zip \ + soap \ + ldap + +# Enable Apache modules +RUN a2enmod rewrite headers + +# Copy application files if REPO_URL is "local" +COPY . /var/www/html-local/ + +# Set working directory +WORKDIR /var/www/html + +# Copy entrypoint script +COPY docker-entrypoint-init.sh /docker-entrypoint-init.sh +RUN chmod +x /docker-entrypoint-init.sh + +# Set permissions +RUN chown -R www-data:www-data /var/www/html + +EXPOSE 80 + +ENTRYPOINT ["/docker-entrypoint-init.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index 02bacd4fa..e592f217f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,62 +1,51 @@ -version: '3.9' services: - vite: + openxe: build: context: . - dockerfile: docker/Dockerfile - target: frontend - image: openxe_frontend - entrypoint: npm run dev - volumes: - - .:/app + dockerfile: Dockerfile + args: + BRANCH: ${BRANCH:-main} + REPO_URL: ${REPO_URL:-local} + image: openxe:dev + container_name: openxe-app ports: - - "5173:5173" - app_init: - image: openxe:test - volumes: - - .:/var/www/html - working_dir: /var/www/html/upgrade - entrypoint: php data/upgrade.php -db -do - depends_on: - mysql: - condition: service_healthy - app: - build: - context: . - dockerfile: docker/Dockerfile - image: openxe:test + - "80:80" + environment: + DB_HOST: db + DB_NAME: openxe + DB_USER: openxe + DB_PASSWORD: openxe + REPO_URL: ${REPO_URL:-local} + BRANCH: ${BRANCH:-main} + IMPORT_SAMPLE: ${IMPORT_SAMPLE:-false} + ADMIN_PASSWORD: ${ADMIN_PASSWORD:-openxe} + TZ: Europe/Berlin volumes: - - .:/var/www/html - ports: - - "8081:80" + - ./userdata:/var/www/html/userdata depends_on: - app_init: - condition: service_completed_successfully - mysql: + db: condition: service_healthy - mysql: + restart: unless-stopped + + db: image: mariadb:10.11 + container_name: openxe-db environment: - MYSQL_ROOT_PASSWORD: "rootpw" - MYSQL_USER: "openxe" - MYSQL_PASSWORD: "openxe" - MYSQL_DATABASE: "openxe" + MYSQL_ROOT_PASSWORD: rootpw + MYSQL_USER: openxe + MYSQL_PASSWORD: openxe + MYSQL_DATABASE: openxe MARIADB_AUTO_UPGRADE: "1" volumes: - - mysqldata:/var/lib/mysql + - dbdata:/var/lib/mysql ports: - "3306:3306" healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 5s - retries: 3 - test: - [ - "CMD", - "healthcheck.sh", - "--connect", - "--innodb_initialized" - ] timeout: 30s + retries: 3 + restart: unless-stopped volumes: - mysqldata: {} \ No newline at end of file + dbdata: diff --git a/docker-entrypoint-init.sh b/docker-entrypoint-init.sh new file mode 100644 index 000000000..d2bebe086 --- /dev/null +++ b/docker-entrypoint-init.sh @@ -0,0 +1,175 @@ +#!/bin/bash +set -e + +# user.inc.php automatisch mit Umgebungsvariablen füllen, nur wenn noch nicht vorhanden +if [ ! -f /var/www/html/conf/user.inc.php ]; then + echo "[Entrypoint] Erstelle user.inc.php ..." + mkdir -p /var/www/html/conf + cat > /var/www/html/conf/user.inc.php <WFdbhost='${DB_HOST:-db}'; +\$this->WFdbname='${DB_NAME:-openxe}'; +\$this->WFdbuser='${DB_USER:-openxe}'; +\$this->WFdbpass='${DB_PASSWORD:-openxe}'; +\$this->WFuserdata='/var/www/html/userdata'; +EOF + chown www-data:www-data /var/www/html/conf/user.inc.php +else + echo "[Entrypoint] user.inc.php existiert bereits, überspringe Erstellung." +fi + +echo "[Entrypoint-DEBUG] REPO_URL=$REPO_URL" +# Standardwerte +BRANCH="${BRANCH:-main}" +REPO_URL="${REPO_URL:-local}" +IMPORT_SAMPLE="${IMPORT_SAMPLE:-false}" + +# Nur klonen, wenn explizit ein anderes REPO_URL als das lokale Repo gesetzt wurde +if [ -n "$REPO_URL" ] && [ "$REPO_URL" != "local" ]; then + echo "[Entrypoint] Klone Repo $REPO_URL (Branch: $BRANCH) ..." + + # Lösche alles außer userdata und conf + find /var/www/html -mindepth 1 -not -path '/var/www/html/userdata*' -not -path '/var/www/html/conf*' -delete 2>/dev/null || true + + # Klone Repository + git clone --branch "$BRANCH" --single-branch "$REPO_URL" /var/www/html-tmp + + # Kopiere alle Dateien außer .git ins Ziel + shopt -s dotglob + cp -r /var/www/html-tmp/* /var/www/html/ 2>/dev/null || true + rm -rf /var/www/html-tmp + + chown -R www-data:www-data /var/www/html +else + echo "[Entrypoint] Lokaler Code wird verwendet, kein Klonen." + # Kopiere lokalen Code wenn /var/www/html leer ist + if [ ! -f /var/www/html/index.php ]; then + echo "[Entrypoint] Kopiere lokalen Code ..." + shopt -s dotglob + cp -r /var/www/html-local/* /var/www/html/ 2>/dev/null || true + chown -R www-data:www-data /var/www/html + fi +fi + +# Warten bis DB erreichbar ist +if [ -n "$DB_HOST" ]; then + echo "[Entrypoint] Warte auf Datenbank ($DB_HOST) ..." + until mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1" >/dev/null 2>&1; do + echo "[Entrypoint] Warte auf MySQL..." + sleep 2 + done + echo "[Entrypoint] Datenbank ist erreichbar." +fi + +# Prüfe ob DB leer ist und importiere ggf. Struktur und Beispieldaten +echo "[Entrypoint] Prüfe Datenbank-Status ..." + +# MySQL-Client verwenden statt PHP +TABLES=$(mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -sN -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME';" 2>/dev/null || echo "0") +TABLES=$(echo "$TABLES" | tr -d '[:space:]') + +# Fallback auf 0, wenn TABLES leer ist +TABLES=${TABLES:-0} + +echo "[Entrypoint] Gefundene Tabellen: $TABLES" + +if [ "$TABLES" -eq 0 ] 2>/dev/null; then + echo "[Entrypoint] Datenbank ist leer, initialisiere mit OpenXE Upgrade-System ..." + + # Nutze das OpenXE Upgrade-System für eine saubere Initialisierung + if [ -f /var/www/html/upgrade/data/upgrade.php ]; then + echo "[Entrypoint] Führe OpenXE Upgrade (upgrade.php -db -do) aus ..." + cd /var/www/html/upgrade + php data/upgrade.php -db -do + if [ $? -eq 0 ]; then + echo "[Entrypoint] OpenXE Upgrade erfolgreich abgeschlossen." + else + echo "[Entrypoint] WARNUNG: OpenXE Upgrade hat Fehler gemeldet (kann normal sein)." + fi + else + echo "[Entrypoint] WARNUNG: upgrade.php nicht gefunden, versuche manuellen Import ..." + + # Fallback: Manueller Import + if [ -f /var/www/html/database/struktur.sql ]; then + echo "[Entrypoint] Importiere Datenbankstruktur (struktur.sql) ..." + # Setze SQL Mode um DEFINER und Strict Mode Probleme zu vermeiden + mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -e "SET GLOBAL sql_mode='NO_ENGINE_SUBSTITUTION';" + sed 's/DEFINER=[^ ]*//g' /var/www/html/database/struktur.sql | \ + mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" + if [ $? -eq 0 ]; then + echo "[Entrypoint] Struktur erfolgreich importiert." + else + echo "[Entrypoint] FEHLER beim Import der Struktur!" + fi + fi + fi + + # Importiere Beispieldaten, wenn IMPORT_SAMPLE=true + if [ "$IMPORT_SAMPLE" = "true" ]; then + if [ -f /var/www/html/database/beispiel.sql ]; then + echo "[Entrypoint] Importiere Beispieldaten (beispiel.sql) ..." + mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < /var/www/html/database/beispiel.sql + if [ $? -eq 0 ]; then + echo "[Entrypoint] Beispieldaten erfolgreich importiert." + else + echo "[Entrypoint] WARNUNG: Fehler beim Import der Beispieldaten." + fi + else + echo "[Entrypoint] WARNUNG: beispiel.sql nicht gefunden unter /var/www/html/database/beispiel.sql" + fi + else + echo "[Entrypoint] IMPORT_SAMPLE ist nicht aktiviert, überspringe Beispieldaten." + fi + + # Erstelle Admin-User mit Passwort + ADMIN_PASSWORD="${ADMIN_PASSWORD:-openxe}" + echo "[Entrypoint] Erstelle Admin-User (Login: admin, Passwort: $ADMIN_PASSWORD) ..." + + # Generiere Passwort-Hash (bcrypt für OpenXE) + ADMIN_PASSWORD_HASH=$(php -r "echo password_hash('$ADMIN_PASSWORD', PASSWORD_BCRYPT);") + + # Prüfe ob User bereits existiert + USER_EXISTS=$(mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -sN -e "SELECT COUNT(*) FROM user WHERE username='admin';" 2>/dev/null || echo "0") + USER_EXISTS=$(echo "$USER_EXISTS" | tr -d '[:space:]') + USER_EXISTS=${USER_EXISTS:-0} + + if [ "$USER_EXISTS" -eq 0 ]; then + # Erstelle neuen Admin-User + mysql --skip-ssl -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" <