Kapitel 6

Deployment

Wie Code auf den Server kommt — und wie man merkt, dass er dort auch funktioniert. Der reguläre Weg ist ein Skript, das nach dem Neustart tatsächlich nachfragt, ob der Dienst wieder antwortet.

Zwei Wege

Es gibt zwei Wege, produktiv zu deployen, und einen dritten Workflow, der nur prüft.

Deployment-Wege
WegAuslöserUmfang
./deploy.sh <service>Manuell auf dem ServerGit-Check, Build, Push, Neustart, Healthcheck, Smoke-Test
GitHub Actions (workflow_dispatch)Manuell in der GitHub-OberflächeBuild, Push, Deploy per SSH — ohne Healthcheck und Smoke-Test
CI (ci.yml)Automatisch bei Push und Pull RequestLint, Unit-Tests, Typecheck — deployt nichts

deploy.sh ist vorzuziehen, weil es nach dem Neustart tatsächlich prüft, ob der Dienst antwortet. Die Actions-Workflows sind der Fallback, wenn gerade kein Server-Zugang besteht.

  1. 1 Git-Check

    Arbeitsverzeichnis sauber?

    Abbruch bei: Uncommittete Änderungen

  2. 2 Build

    docker build --no-cache

    Abbruch bei: Fehlender Patch, fehlende Datei

  3. 3 Push

    registry.raspb.eu

    Abbruch bei: Registry nicht erreichbar

  4. 4 Neustart

    dc-all up -d

    Abbruch bei: Container startet nicht

  5. 5 Healthcheck

    warten auf „healthy“

    Abbruch bei: Timeout nach 30 s bzw. 60 s

  6. 6 Smoke-Test

    curl auf echten Endpunkt

    Abbruch bei: Antwort ist nicht 200

Voraussetzungen

  • Docker mit Zugriff auf registry.raspb.eu
  • Die Compose-Dateien unter /root/compose
  • Eine .env mit den Produktivwerten — Vorlage ist .env.example im Repo-Root
  • Ein sauberes Arbeitsverzeichnis; deploy.sh bricht sonst ab

Cockpit deployen

Cockpit bauen und deployen
cd /root/repos/wein-onlineshop/cockpit
npm run check && npm run test     # muss grün sein
npm run build                     # erzeugt build/ via adapter-node

cd /root/repos/wein-onlineshop
./deploy.sh cockpit

Der Build-Kontext des Dockerfiles ist bewusst das Repo-Root, weil das Cockpit packages/ einbindet. Ein Build aus dem Verzeichnis cockpit/ heraus schlägt fehl — das ist kein Fehler in der Konfiguration, sondern die Folge des Monorepos.

Medusa deployen

Anderes Repository, anderer Paketmanager: Medusa liegt außerhalb des Monorepos und benutzt Yarn 4.

Medusa bauen und deployen
cd /root/workspace/projects/my-medusa-store
yarn install                      # NIEMALS npm
docker build -f Dockerfile .      # ca. 8 Minuten

cd /root/repos/wein-onlineshop
./deploy.sh medusa

Zwei absichtliche Abbrüche im Build

Der Docker-Build enthält zwei Prüfungen, die ihn abbrechen lassen. Beide sind kein Bug, sondern eine Absicherung:

  1. Stripe-Connect-Patch. @medusajs/payment-stripe ist exakt auf 2.13.1 gepinnt. Der Build prüft die Version jeder gehoisteten Kopie, spielt den Patch überall ein und verifiziert danach, dass die zur Laufzeit geladene Kopie on_behalf_of enthält. Ohne diesen Patch findet Stripe Elements den Payment Intent im Connected Account nicht.
  2. Gutschein-Modul. Der Build prüft, dass alle neun kompilierten Dateien — Modul, Service, Admin- und Store-Routen, Subscriber, PDF-Erzeugung und E-Mail-Vorlage — im Image liegen.

Storefront deployen

Storefront bauen und deployen
cd /root/repos/wein-onlineshop/storefronts/<slug>
npm run check && npm run test
npm run build

cd /root/repos/wein-onlineshop
./deploy.sh storefront-<slug>
Eckdaten je Dienst
DienstDockerfileImageHealthcheckSmoke-Test
Cockpitcockpit/Dockerfileweinshop-cockpit30 scockpit.raspb.eu/login
Medusaeigenes Repositorymedusa60 smedusa.raspb.eu/health
Storefrontstorefronts/<slug>/Dockerfileweinshop-storefront-<slug>30 sshop-<slug>.raspb.eu/katalog

Datenbank-Migrationen

Migrationen ausführen
cd /root/workspace/projects/my-medusa-store
npx medusa db:migrate

Wann: Nach jeder Änderung an einer Modell-Datei unter medusa/src/modules/*/models/ — also bei neuen Feldern, neuen Entitäten oder geänderten Relationen.

Smoke-Tests

deploy.sh führt sie automatisch aus. Von Hand geht es so:

Smoke-Tests von Hand
curl -s -o /dev/null -w "Cockpit:    %{http_code}\n" https://cockpit.raspb.eu/login
curl -s -o /dev/null -w "Medusa:     %{http_code}\n" https://medusa.raspb.eu/health
curl -s -o /dev/null -w "Zimmermann: %{http_code}\n" https://shop-zimmermann.raspb.eu/katalog

Erwartet wird überall 200. Zwei Sonderfälle sind zu kennen:

  • 401 ist bei geschützten Admin-Endpunkten in Ordnung. Es belegt, dass Medusa läuft und die Authentifizierung greift.
  • 502 oder 000 heißt: Container nicht erreichbar. Dann docker logs prüfen.

Registry

Alle Images liegen in der privaten Registry:

  • registry.raspb.eu/weinshop-cockpit:latest
  • registry.raspb.eu/weinshop-storefront-<slug>:latest
  • registry.raspb.eu/medusa:latest

Die GitHub-Actions-Workflows melden sich mit den Secrets REGISTRY_USER und REGISTRY_PASS an; der Deploy per SSH nutzt SERVER_HOST und SSH_PRIVATE_KEY.

Fehlerbilder

Diese Tabelle beantwortet die meisten Fragen, die beim Deployen aufkommen. Sie ist aus tatsächlich aufgetretenen Fällen entstanden, nicht aus Vermutungen.

Symptom, Ursache, Abhilfe
SymptomUrsacheAbhilfe
„Es gibt uncommittete Änderungen!“deploy.sh prüft den Git-StatusCommitten oder stashen, dann erneut starten
Build bricht mit „Patch-Basis ist 2.13.1“ ab@medusajs/payment-stripe wurde angehobenAuf 2.13.1 zurückpinnen (ohne Caret) oder den Patch neu erstellen
Build bricht mit „FEHLT im Build: …“ abEine Gutschein-Datei fehlt im KompilatPrüfen, ob die Quelldatei existiert und der Build sie erfasst
Stripe-Zahlungsbox bleibt leerConnect-Patch nicht im laufenden ImageNeu bauen — nicht per docker cp nachbessern, das überlebt keinen Neustart
Änderung ist nach Neustart wegPer docker cp eingespielt statt gebautSauberen Docker-Build fahren
Rechnungs-PDF hängt oder läuft in einen TimeoutDie Vorlage wartet auf externe BilderAuf domcontentloaded warten statt auf load
Healthcheck-TimeoutContainer startet nicht durchdocker logs prüfen; bei Medusa meist eine fehlende Migration
Storefront zeigt keine ProdukteFalscher Sales Channel oder Publishable KeyCompose-Datei des Mandanten prüfen
Unit-Tests schlagen unerklärlich fehlAbweichende Paketversion durch npm-HoistingVersion im betroffenen Paket direkt prüfen