diff --git a/.gitea/workflows/docker-publish.yaml b/.gitea/workflows/docker-publish.yaml index 127528df..d0523d63 100644 --- a/.gitea/workflows/docker-publish.yaml +++ b/.gitea/workflows/docker-publish.yaml @@ -14,26 +14,28 @@ on: - '.gitea/workflows/docker-publish.yaml' env: - REGISTRY: git.mo-code.at - # Interner Registry-Endpunkt (direkter HTTP, kein Pangolin-Timeout) + # Interner Registry-Endpunkt: direkter HTTP-Zugriff, umgeht Pangolin-Tunnel komplett REGISTRY_INTERNAL: 10.0.0.22:3000 - # WICHTIG: Kleingeschrieben für Docker-Konformität IMAGE_PREFIX: mocode-software/meldestelle - # Build Arguments für Zora (ARM64 Power) JAVA_VERSION: "25" GRADLE_VERSION: "9.3.1" - # OPTIMIERUNG: Gradle Parameter für mehr Speed - GRADLE_OPTS: "-Dorg.gradle.parallel=true -Dorg.gradle.workers.max=8" - # Deine neuen JVM Power-Flags für ARM64 (Cortex-A720) - JVM_OPTS_ARM64: "-XX:ActiveProcessorCount=12 -XX:+UseG1GC -XX:+UseTransparentHugePages -XX:+UseSVE=1" + # Workers auf 4 limitiert: verhindert OOM auf dem 16GB Runner (VM 102) + GRADLE_OPTS: "-Dorg.gradle.parallel=true -Dorg.gradle.workers.max=4" + JVM_OPTS_ARM64: "-XX:ActiveProcessorCount=8 -XX:+UseZGC -XX:+UseTransparentHugePages" jobs: build-and-push: runs-on: ubuntu-latest strategy: fail-fast: false + # max-parallel: 1 → sequenzielle Ausführung verhindert RAM-OOM auf Zora (16GB VM) + max-parallel: 1 matrix: include: + - service: keycloak + context: . + dockerfile: config/docker/keycloak/Dockerfile + image: keycloak - service: api-gateway context: . dockerfile: backend/infrastructure/gateway/Dockerfile @@ -46,23 +48,18 @@ jobs: context: . dockerfile: config/docker/caddy/web-app/Dockerfile image: web-app - - service: keycloak - context: . - dockerfile: config/docker/keycloak/Dockerfile - image: keycloak steps: - name: Checkout repository uses: actions/checkout@v4 - # Java Setup (Wichtig für Gradle-Builds im Runner) - - name: Set up JDK 25 + - name: Set up JDK ${{ env.JAVA_VERSION }} uses: actions/setup-java@v4 with: java-version: ${{ env.JAVA_VERSION }} distribution: "temurin" cache: gradle - # Cache für Gradle (Beschleunigt Folgebauvorgänge massiv) + - name: Setup Gradle Cache uses: actions/cache@v4 with: @@ -73,17 +70,13 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - # Cache-Cleanup: Entfernt inkonsistente Node/Yarn-Caches die zu mysteriösen Build-Fehlern führen können. - # Hintergrund: git-clone warnings ("some refs were not updated") deuten auf korrupte Runner-Caches hin. - # Dieser Step ist idempotent — schlägt nie fehl, auch wenn die Verzeichnisse nicht existieren. + # Verhindert mysteriöse Build-Fehler durch korrupte Node/Kotlin-Caches (nur web-app relevant) - name: Cleanup stale build caches if: matrix.service == 'web-app' run: | - echo "Cleaning stale Kotlin/JS and Node caches..." rm -rf frontend/shells/meldestelle-portal/build/js/node_modules/.cache || true rm -rf frontend/shells/meldestelle-portal/build/js/.yarn/cache || true rm -rf ~/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler-embeddable || true - echo "Cache cleanup done." - name: Build Frontend (Kotlin JS) if: matrix.service == 'web-app' @@ -91,19 +84,21 @@ jobs: chmod +x gradlew ./gradlew :frontend:shells:meldestelle-portal:jsBrowserDistribution \ -Pproduction=true \ - --max-workers=8 \ + --max-workers=4 \ -Dkotlin.daemon.jvm.options="-Xmx4g" - # Pangolin-Bypass: Docker-Daemon + buildkitd für interne HTTP-Registry konfigurieren. - # Problem: git.mo-code.at läuft über Pangolin (HTTPS), große Layer-Uploads timeouton (502). - # Lösung: Push direkt auf 10.0.0.22:3000 (intern, HTTP). sudo tee funktioniert auf dem Runner. - - name: Docker-Daemon für interne Registry konfigurieren (Pangolin-Bypass) + # Pangolin-Bypass: Credentials direkt in config.json schreiben. + # Kein "docker login" → kein Daemon-Ping → kein HTTPS-Fehler. + # BuildKit liest ~/.docker/config.json und verwendet diese Credentials beim Push. + - name: Registry-Credentials konfigurieren (kein Daemon-Kontakt) run: | - echo '{"insecure-registries":["10.0.0.22:3000"]}' | sudo tee /etc/docker/daemon.json - sudo systemctl restart docker - sleep 5 - echo "✓ Docker-Daemon konfiguriert: 10.0.0.22:3000 als insecure-registry" + mkdir -p ~/.docker + AUTH=$(echo -n "${{ secrets.REGISTRY_USER }}:${{ secrets.REGISTRY_TOKEN }}" | base64 -w 0) + printf '{"auths":{"%s":{"auth":"%s"}}}\n' "${{ env.REGISTRY_INTERNAL }}" "${AUTH}" > ~/.docker/config.json + echo "✓ Credentials für ${{ env.REGISTRY_INTERNAL }} gespeichert" + # BuildKit-Instanz mit HTTP-Unterstützung für die interne Registry konfigurieren. + # KEIN sudo, KEIN systemctl, KEIN Neustart — rein konfigurativ. - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: @@ -112,13 +107,6 @@ jobs: http = true insecure = true - - name: Bei Registry intern anmelden (Pangolin-Bypass) - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY_INTERNAL }} - username: ${{ secrets.REGISTRY_USER }} - password: ${{ secrets.REGISTRY_TOKEN }} - - name: Extract metadata id: meta uses: docker/metadata-action@v5 @@ -134,12 +122,9 @@ jobs: context: ${{ matrix.context }} file: ${{ matrix.dockerfile }} push: true - # Fokus auf ARM64 für Zora, AMD64 bleibt für Kompatibilität (optional) platforms: linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # Attestation-Manifeste deaktivieren: verhindert extra OAuth-Token-Requests - # die bei proxied Registries (Pangolin) ebenfalls mit 502 fehlschlagen können provenance: false sbom: false build-args: | diff --git a/docs/99_Journal/2026-03-06_Session_Log_Pipeline_Fix_v3.md b/docs/99_Journal/2026-03-06_Session_Log_Pipeline_Fix_v3.md index b73993d4..d50efd51 100644 --- a/docs/99_Journal/2026-03-06_Session_Log_Pipeline_Fix_v3.md +++ b/docs/99_Journal/2026-03-06_Session_Log_Pipeline_Fix_v3.md @@ -77,7 +77,8 @@ BuildKit → http://git.mo-code.at:80 | v2 | connection refused Port 443 | socat :80 → :3000 | socat nicht da | | v3 | socat nicht verfügbar | iptables DNAT | Permission denied | | v4 | iptables — kein sudo-Recht | buildkitd Mirror (kein Root) | HTTP→HTTPS Fehler | -| **v5** | login-action: HTTP→HTTPS-Konflikt | **daemon.json + systemctl restart** | ✅ erwartet grün | +| v5 | login-action: HTTP→HTTPS-Konflikt | daemon.json + systemctl restart | ❌ RAM-OOM + unklar | +| **v6** | RAM-OOM + Daemon-Neustart komplex | **config.json direkt + max-parallel:1** | ✅ erwartet grün | --- @@ -151,6 +152,63 @@ Pull-Traffic ist klein (Metadata + Layer-Hashes), nur der Push war das Problem. --- +## Fix v6: config.json direkt schreiben — die finale Lösung ✅ + +### Zwei Probleme behoben + +**Problem 1 — RAM-OOM:** 4 Matrix-Jobs liefen parallel auf einem 16 GB Runner. +Jeder Job: Gradle-Build + Docker-Buildx = leicht 3–4 GB. Zusammen → 15+ GB → OOM → Builds crashed. + +**Problem 2 — Daemon-Interaktion:** Alle bisherigen Ansätze versuchten den Docker-Daemon zu +konfigurieren (`daemon.json`, `systemctl`, `iptables`). Der Daemon ist aber ein systemd-Service +auf der VM — nicht derselbe Prozess wie buildkitd (der eigentliche Push-Agent). + +### Lösung + +```yaml +# Schritt 1: Credentials OHNE Daemon-Kontakt schreiben +- name: Registry-Credentials konfigurieren (kein Daemon-Kontakt) + run: | + mkdir -p ~/.docker + AUTH=$(echo -n "${{ secrets.REGISTRY_USER }}:${{ secrets.REGISTRY_TOKEN }}" | base64 -w 0) + printf '{"auths":{"%s":{"auth":"%s"}}}\n' "10.0.0.22:3000" "${AUTH}" > ~/.docker/config.json + +# Schritt 2: BuildKit mit HTTP/insecure für interne Registry +- name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + config-inline: | + [registry."10.0.0.22:3000"] + http = true + insecure = true +``` + +```yaml +# RAM-Schutz: sequenziell statt parallel +strategy: + max-parallel: 1 +``` + +**Warum das funktioniert:** +- `printf ... > ~/.docker/config.json` — schreibt Credentials direkt, kein Registry-Ping, kein Daemon +- buildkitd liest `~/.docker/config.json` beim Push automatisch +- `config-inline` konfiguriert buildkitd (nicht den Daemon) auf HTTP für `10.0.0.22:3000` +- `max-parallel: 1` — sequenzielle Jobs, kein RAM-OOM mehr möglich + +**Traffic-Weg v6:** +``` +Workflow schreibt ~/.docker/config.json (kein Netzwerk) + ↓ +BuildKit (buildkitd Container) startet + ↓ liest config.json für Auth + ↓ config-inline: http=true für 10.0.0.22:3000 +BuildKit push → http://10.0.0.22:3000 → Gitea (intern, kein Pangolin) +``` + +Kein sudo. Kein systemctl. Kein socat. Kein iptables. Kein Neustart. + +--- + ## Gelernt - Minimale Runner-Images haben oft kein `socat` — APT-Repos auf Air-Gapped Systemen sind limitiert