Deployment von containerisierten Anwendungen mit GitHub Actions
Mit GitHub Actions kannst du dein Container-Image direkt aus deinem Quellcode-Repository erstellen und veröffentlichen und dann sofort deine Anwendung auf der mittwald Cloud-Plattform deployen. Die offizielle mittwald/deploy-container-action kümmert sich um die API-Aufrufe, wendet deine Stack-Definition an und erstellt (falls erforderlich) die betroffenen Dienste neu.
Voraussetzungen
- mStudio API-Token; siehe die Dokumentation zu API-Token erhalten
 - Stack-ID; siehe die Dokumentation zu Standard-Stack identifizieren
 - (Optional) Private Registry; siehe Verwendung privater Registries
 - GitHub Actions Runner; jeder Runner mit Docker-Unterstützung, z.B. 
ubuntu-latest 
Identifiziere deinen Stack
Folge der Dokumentation zu Standard-Stack identifizieren deines Projekts. Zur Vereinfachung empfehlen wir, die Stack-ID in einer GitHub-Variablen zu speichern, z.B. STACK_ID.
Schreibe deine stack.yaml
Erstelle als nächstes eine Datei, die deine Stack-Definition irgendwo in deinem Repository enthält (für dieses Beispiel nehmen wir an, deploy/stack.yaml). Diese Datei sollte das gleiche Format wie die PUT/-Operation haben.
services:
  app:
    image: ghcr.io/<OWNER>/<REPO>:{{ .Env.IMAGE_TAG }}
    description: "Meine Webanwendung"
    ports:
      - "8080/tcp"
    envs:
      APP_ENV: production
volumes: {}
Die Platzhalter innerhalb von {{ … }} werden aus Umgebungsvariablen aufgelöst, die du im Workflow übergibst, sodass deine Secrets in GitHub bleiben und niemals im Repository eingecheckt werden müssen.
Füge Geheimnisse und Variablen zum Repository hinzu
MITTWALD_API_TOKEN; API-Token für die mStudio-APISTACK_ID; die in Schritt 1 kopierte ID. Du könntest dies als einfache Konfigurationsvariable festlegen, könntest diese Variable aber auch deiner Ziel-Environment zuordnen, wenn du environment-abhängig in verschiedene Stacks deployen möchtest.
Erstelle den GitHub Action Workflow
Erstelle .github/workflows/deploy.yml:
name: Build & Deploy to mittwald
on:
  push:
    branches: [main]
  # alternativ:
  # push:
  #   tags: [v*]
  workflow_dispatch:
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      attestations: write
      id-token: write
    environment:
      name: production
      url: https://your-app.example
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - name: Anmelden bei GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Metadaten (Tags, Labels) für Docker extrahieren
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
      - name: Build & Push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
      - name: Bereitstellung an mStudio
        uses: mittwald/deploy-container-action@v1
        env:
          IMAGE_TAG: ${{ github.sha }}
        with:
          api_token: ${{ secrets.MITTWALD_API_TOKEN }}
          stack_id: ${{ vars.STACK_ID }}
          stack_file: "${{ github.workspace }}/configs/stack.yaml"
Mit diesem Workflow wird bei jedem Push zu main (oder je nach Konfiguration, bei jedem neuen Git-Tag) GitHub ein neues Image erstellen, es in die GitHub Container Registry hochladen und die neuen Images ins mStudio deployen.
Fortgeschrittene Muster
Selektive Neustarts
Wenn du Ausfallzeiten für zustandsbehaftete Dienste (z.B. Datenbanken) vermeiden möchtest, kannst du der Action sagen, dass sie die Neuerstellung nach dem Update überspringen soll:
with:
  skip_recreation: "mysql,redis"
Nicht aufgelistete Dienste werden nur neu gestartet, wenn die API meldet, dass ein Neustart tatsächlich erforderlich ist.
Nächste Schritte
- Füge ein Ingress hinzu, um HTTP-Ports für das öffentliche Internet freizugeben.
 - Verwende Terraform für vollständig deklarative Infrastruktur und lasse GitHub Actions 
terraform applyaufrufen. - Definiere Umgebungen dynamisch pro Pull-Request, um kurzlebige Überprüfungsumgebungen für jeden PR zu erstellen.