- scripts/release.sh: build from main, tag :latest + short SHA, push both. Aborts if not on main or working tree is dirty; warns on unpushed commits. Prevents dev states from becoming :latest. - scripts/dev-build.sh: local dev image (tagged per branch), never pushed -- keeps development builds off the registry. - docs/deployment.md: document branch/PR workflow, replace manual build/push steps with the scripts, SHA-based rollback now standard. - .gitattributes: force LF on *.sh so the shebang works on Windows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.5 KiB
Deployment
Wie ein neuer Stand der Website auf Unraid landet. Aktueller Stand: Handbetrieb — Image lokal bauen, in die Gitea-Registry pushen, auf Unraid ziehen. Die Automatisierung per Gitea Actions (plan.md Schritt 10) kommt später.
Test- vs. Produktivbetrieb. Solange die Domain noch nicht umgezogen ist und NPM nicht davorsteht, läuft der Container mit einem Port-Mapping und ist im lokalen Netz direkt erreichbar (
http://<unraid>:5000). Im Produktivbetrieb entfällt das Mapping — dann ist nur NPM der Weg zum Container (plan.md AE-4, Abschnitt 8). Die beiden compose-Varianten sind unten getrennt beschrieben.
Voraussetzungen (einmalig)
Gitea-Registry-Token
Der Push in die Registry braucht ein Gitea-Zugriffstoken mit Paket-Schreibrecht
(package: Read and Write) — nicht das Kontopasswort.
- Gitea → oben rechts Profilbild → Settings → Applications.
- Abschnitt Manage Access Tokens: Name vergeben (z.B.
registry-push). - Unter Select scopes:
packageauf Read and Write stellen. - Generate Token klicken, Zeichenkette sofort kopieren (nur einmal sichtbar).
Token ist ein Geheimnis. Niemals in Git, Chats, Screenshots oder Tickets im Klartext ablegen. Wird eins doch einmal sichtbar: in Gitea löschen und neu erzeugen. Ein
package-Token erlaubt das Hochladen beliebiger Images in die Registry.
Der Docker-Login speichert das Token danach lokal, sodass es nur einmal eingegeben werden muss.
Arbeitsweise: Branches, nie direkt auf main
main ist der veröffentlichte Stand — nur daraus wird :latest gebaut, und
nur :latest zieht Unraid. Deshalb wird nie direkt auf main committet:
- Feature-Branch anlegen:
git switch -c <bereich>/<kurz>(z.B.deployment/sha-tagging,content/pipeline). - Dort committen, Branch pushen:
git push -u origin <branch>. - In Gitea einen Pull Request gegen
mainöffnen und dort mergen. - Erst danach aus
maindas Release-Image bauen (unten).
Dev-Images bleiben lokal. Zum Ausprobieren auf dem eigenen Rechner:
scripts/dev-build.sh # baut elternbeirat-web:dev-<branch>, pusht NICHTS
So kann ein Entwicklungsstand nie versehentlich als :latest in der Registry
landen.
Neuen Stand ausrollen (Handbetrieb)
Voraussetzung: einmalig an der Registry angemeldet (siehe unten). Dann, auf main und mit sauberem Arbeitsverzeichnis:
scripts/release.sh
Das Skript baut das Image, taggt es mit :latest und dem Commit-Kurz-SHA
(für Rollback) und pusht beide. Es bricht ab, wenn du nicht auf main bist
oder uncommittete Änderungen hast, und warnt bei ungepushten Commits.
Der Image-Pfad
gitea.anticarnist.de/tom/elternbeiratist kleingeschrieben — Container-Registries verlangen das im Pfad, obwohl Benutzer (Tom) und Repo (Elternbeirat) großgeschrieben sind.
Unraid einmalig an der Registry anmelden
Das Image ist privat, deshalb muss Unraid sich einmal anmelden, bevor es
ziehen kann. Das Compose Manager Plus-Plugin hat dafür kein UI-Feld — der
Login läuft über das Unraid-Terminal (>_-Symbol oben rechts in der
Weboberfläche, Prompt root@Cube:~#):
docker login gitea.anticarnist.de
# Username: Tom
# Password: <package-Token>
Der Login bleibt gespeichert; er muss nur wiederholt werden, wenn das Token wechselt. Zwei erfahrungsgemäße Stolpersteine:
- Nicht mit PowerShell/Laptop verwechseln. Der Login muss im Unraid-Terminal
passieren (
root@Cube), nicht in der Windows-PowerShell (PS C:\). Der Laptop braucht den Login nur zum Pushen, Unraid zum Ziehen. - Falscher Username bleibt hängen. Meldet der Login „Stored credentials
invalid or expired" und fragt nicht nach dem Namen, erst
docker logout gitea.anticarnist.de, dann neu einloggen — sonst wird versehentlich ein Nonsens-Username gespeichert. - Klartext-Warnung. Docker speichert das Token unverschlüsselt in
/root/.docker/config.json. Auf dem eigenen Server für den Anfang okay. Später sauberer: einen Credential-Helper einrichten (→ offener Punkt unten).
Auf Unraid neu ziehen und starten
Im Compose Manager Plus-Plugin (Unraid-Weboberfläche):
- Reiter Docker → Abschnitt Compose → Stack elternbeirat →
Compose Down, dann Compose Up (oder „Pull" + „Up", je nach
Plugin-Version), damit die neue
:latestgezogen wird.
docker compose upzieht ein:latestnicht automatisch neu, wenn schon ein gleichnamiges Image lokal liegt. Im Zweifel vorher explizit „Pull".
compose-Varianten
Test (jetzt: ohne NPM, direkt im LAN erreichbar)
Liegt im Repo als compose.yaml. Zieht das Registry-Image und mappt Port
5000 → 8080:
services:
eb-web:
image: gitea.anticarnist.de/tom/elternbeirat:latest
container_name: eb-web
restart: unless-stopped
environment:
ASPNETCORE_URLS: http://+:8080
TZ: Europe/Berlin
ports:
- "5000:8080" # TEST-Zugang, im Produktivbetrieb entfernen
Erreichbar unter http://<unraid>:5000.
Produktiv (später: nur über NPM)
Kein ports:-Block, stattdessen das externe NPM-Docker-Netz (plan.md
Abschnitt 8):
services:
eb-web:
image: gitea.anticarnist.de/tom/elternbeirat:latest
container_name: eb-web
restart: unless-stopped
environment:
ASPNETCORE_URLS: http://+:8080
TZ: Europe/Berlin
networks: [npm]
networks:
npm:
external: true
Rollback
scripts/release.sh taggt jeden Release zusätzlich mit dem Commit-Kurz-SHA, der
sich — anders als das wandernde :latest — nie verschiebt. Zum Zurückrollen in
der Unraid-compose.yaml :latest durch :<sha> des letzten funktionierenden
Stands ersetzen und neu hochfahren:
image: gitea.anticarnist.de/tom/elternbeirat:99dd052 # statt :latest
Welche SHA-Tags in der Registry liegen, zeigt Gitea unter
Tom/-/packages → elternbeirat.
Offene Automatisierung (später, plan.md Schritt 10)
.gitea/workflows/deploy.yml: auf Push nachmainbauen und pushen.- Zwei bekannte Stolpersteine: der
act_runnerbraucht Docker-Socket-Zugriff; die Registry braucht daswrite:package-Token, nicht das Login-Passwort. - Redeploy per Watchtower label-scoped, sonst aktualisiert er den ganzen Home-Lab-Bestand.
- Registry-Token auf Unraid verschlüsseln: aktuell liegt es im Klartext in
/root/.docker/config.json. Später einen Credential-Helper einrichten, damit die Klartext-Warnung vondocker loginverschwindet.