Von git push zu live: die Deployment-Pipeline im Detail

Ausgangslage

Nach jedem Blog-Beitrag wollte ich nicht mehr manuell auf den VPS. Ein git push sollte reichen, um die Seite zu aktualisieren — ohne SSH, ohne docker compose von Hand.

Entscheidung

Statt den gebauten dist/-Ordner per rsync auf den Server zu kopieren, baue ich ein Docker-Image mit Commit-SHA im Tag. Ein Image ist unveränderlich und macht einen Rollback zu einer Tag-Änderung statt zu einem neuen Build — und passt zum Muster, das die künftigen Apps ohnehin brauchen.

Umsetzung

Zwei GitHub-Actions-Jobs: build baut das Image (Multi-Stage, Node → nginx:alpine) und pusht es mit den Tags latest und dem Commit-SHA nach ghcr.io. deploy, nur aktiv wenn die Variable DEPLOY_ENABLED gesetzt ist, verbindet sich per eigenem SSH-Deploy-Key und führt docker compose pull && up -d --force-recreate auf dem VPS aus. Ein Validierungsskript läuft als prebuild-Hook direkt im Image-Build und verhindert fehlende Übersetzungen.

Erkenntnis

Ein grüner Lauf ist nicht automatisch eine fertige Pipeline — bewegliche Referenzen wie ubuntu-latest oder ungepinnte Action-Versionen altern unsichtbar im Hintergrund. Die einzelnen Entscheidungen dahinter stehen im ausführlichen Beitrag Die Pipeline unter der Haube.