From e26481d8df1bec6f703a132057a7774b091bef25 Mon Sep 17 00:00:00 2001 From: DragonSlayer_14 Date: Thu, 10 Sep 2026 00:02:10 +0200 Subject: [PATCH] Feat: Isolierter externer Cache-Service + 5 parallele Jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Cache läuft jetzt als eigener, per Secret authentifizierter Service (config/cache.yaml, Service "cache") statt eingebettet im Runner. Dadurch behält jeder Job weiterhin sein eigenes isoliertes Docker-Netzwerk (auch bei runner.capacity: 5), statt sich wie zuvor ein gemeinsames Netzwerk mit dem Runner und allen anderen Jobs zu teilen - das hätte parallelen/späteren Jobs erlaubt, sich gegenseitig zu erreichen und den unauthentifizierten Cache zu vergiften. Job-Container erreichen den Cache-Server über den Docker-Host-Gateway (container.options: --add-host=cachehost:host-gateway) statt über ein gemeinsames Netzwerk. - runner.capacity: 5 - Cache-Server-Prozess authentifiziert per external_secret_file (cache-secret, wird auf dem Host erzeugt, nicht committet) - Konfigurationen nach config/runner.yaml und config/cache.yaml verschoben - Datenverzeichnisse aufgeteilt in data/runner und data/cache - README: Setup-Anleitung fürs Secret + Migrationsanleitung für bestehende Deployments (alter data/-Inhalt -> data/runner) Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_014kFWpJ4p1jQ2pJf3S13FWE --- .gitignore | 1 + README.md | 60 ++++++++++++++++++++++++++++++++++++++++++++- config.yaml | 16 ------------ config/cache.yaml | 5 ++++ config/runner.yaml | 19 ++++++++++++++ docker-compose.yaml | 26 ++++++++++++++------ 6 files changed, 103 insertions(+), 24 deletions(-) delete mode 100644 config.yaml create mode 100644 config/cache.yaml create mode 100644 config/runner.yaml diff --git a/.gitignore b/.gitignore index 95256db..101ed36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ data/ +cache-secret .vscode .env diff --git a/README.md b/README.md index 036b267..1a3d211 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,61 @@ # gitea_runner -Enthält eine einfache docker-compose, um einen gitea_runner zu starten. \ No newline at end of file +Enthält eine einfache docker-compose, um einen gitea_runner zu starten. + +## Verzeichnisstruktur + +- `config/runner.yaml` — Konfiguration des Runners +- `config/cache.yaml` — Konfiguration des Cache-Servers +- `data/runner` — persistenter Zustand des Runners (u. a. `.runner`-Registrierungsdatei) +- `data/cache` — persistente Cache-Daten +- `cache-secret` — gemeinsames Secret für Runner ↔ Cache-Server (siehe unten, **nicht** in Git) + +## Einrichtung + +Vor dem ersten Start muss auf dem Host ein Secret für die Authentifizierung zwischen +Runner und Cache-Server erzeugt werden: + +```sh +openssl rand -hex 32 > cache-secret +chmod 600 cache-secret +``` + +Diese Datei darf **nicht committet werden** (sie ist über `.gitignore` ausgeschlossen) +und muss auf jedem Host, auf dem dieses Setup läuft, individuell erzeugt werden. + +## Migration von einer älteren Version dieses Compose-Setups + +Frühere Versionen legten die Runner-Daten direkt unter `./data` ab und hatten kein +`config/`-Verzeichnis. Beim Umstieg auf diese Version muss der bestehende Datenordner +verschoben werden, sonst registriert sich der Runner erneut (verwaiste Registrierung +auf der Gitea-Instanz) und der bisherige Cache geht verloren: + +```sh +# Runner vorher stoppen +docker compose down + +# Repository pullen +git pull + +# Vorhandene Daten (u. a. die .runner-Datei) nach data/runner verschieben +mv data data_old +mkdir -p data +mv data_old data/runner + +# Danach ganz normal wieder starten +docker compose up -d +``` + +Falls vorher schon ein eigenständiger Cache-Ordner existierte (z. B. unter +`data/runner/cache` oder `cache-data/` aus einer Zwischenversion), diesen entsprechend +nach `data/cache` verschieben. + +## Cache-Service + +Der Cache läuft als eigener Service (`cache` in `docker-compose.yaml`), getrennt vom +Runner, damit die bis zu 5 parallel laufenden Jobs weiterhin jeweils ihr eigenes, +isoliertes Docker-Netzwerk bekommen und sich nicht gegenseitig erreichen können. +Job-Container erreichen den Cache-Server trotzdem über den Docker-Host (`cachehost` +wird per `--add-host=cachehost:host-gateway` auf das Host-Gateway gemappt, siehe +`config/runner.yaml` -> `container.options`), der Port `8088` des Cache-Servers ist +dafür auf dem Host veröffentlicht. diff --git a/config.yaml b/config.yaml deleted file mode 100644 index 22d634e..0000000 --- a/config.yaml +++ /dev/null @@ -1,16 +0,0 @@ -cache: - enabled: true - # Ohne diese Angabe würde der Cache unter $HOME/.cache/actcache landen, also in der - # Schreibschicht des Containers, und bei jedem Neuerstellen des Containers verloren gehen. - # /data ist in docker-compose.yaml als Volume gemountet, daher ist dieser Pfad persistent. - dir: "/data/cache" - # Job-Container laufen (via container.network) im selben Docker-Netzwerk wie - # dieser Runner-Container, daher ist er dort unter seinem Containernamen erreichbar. - host: "gitea_runner" - port: 8088 - -container: - # Ohne festes Netzwerk erstellt der Runner pro Job ein eigenes, isoliertes Netzwerk, - # aus dem der Job-Container den Cache-Server (siehe cache.host) nicht erreichen kann. - # Daher: gemeinsames, in docker-compose.yaml definiertes Netzwerk verwenden. - network: "gitea_runner_net" diff --git a/config/cache.yaml b/config/cache.yaml new file mode 100644 index 0000000..9c1b9b8 --- /dev/null +++ b/config/cache.yaml @@ -0,0 +1,5 @@ +cache: + dir: /data + host: "0.0.0.0" + port: 8088 + external_secret_file: "/run/cache-secret" diff --git a/config/runner.yaml b/config/runner.yaml new file mode 100644 index 0000000..e0b0948 --- /dev/null +++ b/config/runner.yaml @@ -0,0 +1,19 @@ +runner: + # Bis zu 5 Jobs gleichzeitig. container.network bleibt leer, damit jeder Job weiterhin + # sein eigenes isoliertes Docker-Netzwerk bekommt (kein gegenseitiger Zugriff der Jobs). + capacity: 5 + +cache: + enabled: true + # Dedizierter, separater Cache-Server (siehe cache-config.yaml + docker-compose.yaml, + # Service "cache"), erreichbar über den Docker-Host-Gateway (siehe container.options + # unten), unabhängig vom isolierten Netzwerk des jeweiligen Jobs. + external_server: "http://cachehost:8088/" + external_secret_file: "/run/cache-secret" + +container: + # Jeder Job bekommt ein eigenes, frisches Docker-Netzwerk (network bewusst leer gelassen), + # damit parallele Jobs sich nicht gegenseitig erreichen können. Damit die Job-Container + # trotzdem den externen Cache-Server erreichen, wird "cachehost" auf das Docker-Host-Gateway + # gemappt; der Cache-Server veröffentlicht seinen Port auf dem Host (siehe docker-compose.yaml). + options: "--add-host=cachehost:host-gateway" diff --git a/docker-compose.yaml b/docker-compose.yaml index f21b768..ed4432b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,6 +3,8 @@ services: image: docker.io/gitea/runner:latest container_name: gitea_runner restart: unless-stopped + depends_on: + - cache environment: CONFIG_FILE: /config.yaml GITEA_INSTANCE_URL: "${INSTANCE_URL}" @@ -10,12 +12,22 @@ services: GITEA_RUNNER_NAME: "${RUNNER_NAME}" GITEA_RUNNER_LABELS: "${RUNNER_LABELS}" volumes: - - ./config.yaml:/config.yaml - - ./data:/data + - ./config/runner.yaml:/config.yaml + - ./data/runner:/data + - ./cache-secret:/run/cache-secret:ro - /var/run/docker.sock:/var/run/docker.sock - networks: - - runner + extra_hosts: + - "cachehost:host-gateway" -networks: - runner: - name: gitea_runner_net + cache: + image: docker.io/gitea/runner:latest + container_name: gitea_runner_cache + restart: unless-stopped + entrypoint: ["/sbin/tini", "--", "/usr/local/bin/gitea-runner"] + command: ["-c", "/config.yaml", "cache-server"] + volumes: + - ./config/cache.yaml:/config.yaml + - ./data/cache:/data + - ./cache-secret:/run/cache-secret:ro + ports: + - "8088:8088"