
Docker Compose auf dem VPS: Webserver, Datenbank & Reverse Proxy richtig betreiben
Praxisnaher Guide für Docker Compose auf dem VPS: Webserver, Datenbank, Reverse Proxy, TLS, Backups, Updates und Sicherheit richtig planen und betreiben.
GitHub Actions ist die native CI/CD-Plattform von GitHub, die es ermöglicht, Software-Workflows direkt im Repository zu definieren, zu testen und auszuführen. Seit der allgemeinen Verfügbarkeit im Jahr 2019 hat sich der Dienst kontinuierlich weiterentwickelt und bietet 2026 eine beeindruckende Palette an Funktionen, die mit dedizierten CI/CD-Lösungen wie Jenkins, GitLab CI oder CircleCI konkurriert.
Der größte Vorteil von GitHub Actions liegt in der tiefen Integration in das GitHub-Ökosystem. Pull Requests, Issues, Releases, Tags und Branches sind keine externen Konzepte mehr – sie sind First-Class-Citizens in deiner Pipeline. Ein Kommentar wie /deploy production in einem Pull Request kann eine komplette Deployment-Sequenz auslösen, ohne dass eine externe Orchestrierung notwendig ist.
Die Plattform basiert auf dem Konzept der Events, Workflows, Jobs und Steps. Ein Workflow wird durch ein Event ausgelöst (z. B. push, pull_request), besteht aus einem oder mehreren Jobs, die parallel oder sequenziell laufen, und jeder Job enthält einzelne Steps, die Befehle oder Actions (wiederverwendbare Codebausteine) ausführen.
2026 bietet GitHub Actions zudem erweiterte Features wie GPU-beschleunigte Runner, integrierte OIDC-Authentifizierung für Cloud-Deployments, einen überarbeiteten Workflow-Editor mit KI-gestützten Vorschlägen sowie ein neues Pre-Built-Action-Registry, das kuratierte, sicherheitsgeprüfte Actions von vertrauenswürdigen Anbietern enthält.
Bevor du deine erste Pipeline aufsetzt, solltest du einige technische und organisatorische Voraussetzungen prüfen. Die Grundlagen sind zwar niedrigschwellig – ein GitHub-Account und ein Repository reichen aus – aber für produktionsreife Setups empfiehlt sich eine durchdachte Vorbereitung.
Technisch benötigst du ein GitHub-Konto (Free, Team oder Enterprise), ein Repository mit aktivem Git-Zugriff und grundlegende Kenntnisse in YAML-Syntax. YAML (YAML Ain't Markup Language) ist die Konfigurationssprache für Workflows und folgt strikten Einrückungsregeln – bereits ein einzelnes falsches Leerzeichen kann einen Workflow komplett stoppen.
Je nach Projekt-Stack kommen weitere Anforderungen hinzu: Für Node.js-Projekte wird Node.js (empfohlen LTS) benötigt, für Python-Projekte eine aktuelle Python-Version, für Java-Projekte JDK 17 oder 21. Auch die Konfiguration von Secrets im Repository- oder Organisationsbereich ist essenziell, um sensible Daten wie API-Tokens, Deploy-Schlüssel oder Datenbankzugangsdaten sicher zu hinterlegen.
Organisatorisch solltest du klare Verantwortlichkeiten definieren: Wer darf Workflows bearbeiten? Welche Branches sind geschützt? Welche Secrets werden zentral verwaltet? GitHub bietet hierfür Environments mit Approval-Regeln und Branch Protection Rules, die wir später detailliert besprechen.
| Komponente | Mindestanforderung | Empfohlen für Produktion |
|---|---|---|
| GitHub-Plan | Free | Team oder Enterprise |
| YAML-Kenntnisse | Grundlagen | Fortgeschritten (Anchors, Includes) |
| Secrets-Management | Repository-Secrets | Organisation-Secrets + OIDC |
| Runner-Typ | GitHub-Hosted | Hybrid (Self-Hosted für sensible Workloads) |
| Tooling | Git, Code-Editor | VS Code + GitHub Actions Extension |
Ein GitHub-Actions-Workflow wird als YAML-Datei im Verzeichnis .github/workflows/ deines Repositories definiert. Jede Datei in diesem Ordner stellt einen separaten Workflow dar. Lass uns einen einfachen Einstiegs-Workflow erstellen, der bei jedem Push und Pull Request ausgeführt wird.
Erstelle zunächst die Datei .github/workflows/hello-world.yml in deinem Repository. Der Dateiname ist frei wählbar, sollte aber beschreibend sein. GitHub erkennt automatisch alle *.yml- und *.yaml-Dateien in diesem Verzeichnis.
name: Hello World Workflow
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
greet:
runs-on: ubuntu-latest
steps:
- name: Begrüßung ausgeben
run: echo "Hallo von GitHub Actions! 🚀"
- name: Datum anzeigen
run: date
- name: Runner-Info
run: |
echo "Runner-Betriebssystem: ${{ runner.os }}"
echo "Runner-Architektur: ${{ runner.arch }}"
Dieser minimale Workflow enthält alle Grundbausteine: einen aussagekräftigen Namen, einen Trigger-Block (on), einen Job namens greet, der auf dem aktuellen Ubuntu-Runner läuft, und drei Steps, die einfache Shell-Befehle ausführen. Die Syntax ${{ ... }} ist eine Expression, die zur Laufzeit ausgewertet wird – in diesem Fall der Zugriff auf vordefinierte Kontext-Variablen.
Nach dem Commit und Push in den main-Branch findest du unter dem Tab Actions in deinem Repository den ausgeführten Workflow. Klicke auf den Run, um die Logs der einzelnen Steps einzusehen. Dieser erste Test bildet die Grundlage für alle weiteren Pipelines.
Die GitHub-Actions-Syntax folgt einem klaren Schema. Das Verständnis der einzelnen Bausteine ist entscheidend, um komplexe Pipelines zu modellieren. Die wichtigsten Top-Level-Keys sind name, on, env, defaults, jobs und optional permissions, concurrency sowie permissions.
Der on-Block definiert die Auslöser. Dies können einzelne Events (push, pull_request, workflow_dispatch), zeitbasierte Trigger (schedule mit Cron-Syntax) oder manuelle Trigger sein. Mit workflow_dispatch wird ein Workflow über die GitHub-Oberfläche, die API oder die CLI manuell startbar – ideal für Deployments.
on:
push:
branches: [ main, develop ]
tags: [ 'v*' ]
pull_request:
types: [ opened, synchronize, reopened ]
workflow_dispatch:
inputs:
environment:
description: 'Zielumgebung'
required: true
default: 'staging'
type: choice
options:
- staging
- production
schedule:
- cron: '0 2 * * *'
Der jobs-Block enthält die eigentliche Arbeitslogik. Jeder Job läuft in einer frischen VM, hat einen eigenen runs-on-Runner und kann needs-Abhängigkeiten zu anderen Jobs definieren. Innerhalb eines Jobs werden Steps sequenziell ausgeführt, es sei denn, man setzt continue-on-error oder verwendet Conditional Logic mit if.
Eine Besonderheit sind Matrix-Strategien, mit denen ein Job mehrfach mit unterschiedlichen Parametern ausgeführt wird – etwa verschiedenen Node.js-Versionen, Betriebssystemen oder Node-Versionen. Dies ist besonders wertvoll für Cross-Browser- oder Cross-Platform-Tests.
| Key | Zweck | Pflicht? |
|---|---|---|
name |
Anzeigename des Workflows | Nein |
on |
Trigger (Events) | Ja |
env |
Globale Umgebungsvariablen | Nein |
jobs |
Definition der auszuführenden Jobs | Ja |
permissions |
Token-Berechtigungen (GITHUB_TOKEN) | Nein (Best Practice: explizit setzen) |
concurrency |
Steuerung paralleler Runs | Nein |
Continuous Integration ist das Herzstück jeder modernen Softwareentwicklung. Eine gut konfigurierte CI-Pipeline stellt sicher, dass jeder Commit und jeder Pull Request automatisch gebaut, getestet und auf Codequalität geprüft wird. Lass uns eine realistische CI-Pipeline für eine Node.js-Anwendung aufbauen.
Im folgenden Beispiel klonen wir den Code, richten Node.js ein, installieren Abhängigkeiten mit Caching, führen Linting und Tests aus und bauen das Projekt. Die Verwendung von actions/checkout@v5 und actions/setup-node@v5 entspricht den 2026er-Konventionen – pinning auf Major-Versionen sorgt für Stabilität, automatische Patch-Updates werden per @v5 ermöglicht.
name: CI Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
NODE_VERSION: '20'
jobs:
build-and-test:
name: Build & Test
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Code auschecken
uses: actions/checkout@v5
- name: Node.js einrichten
uses: actions/setup-node@v5
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Abhängigkeiten installieren
run: npm ci
- name: Linting ausführen
run: npm run lint
- name: Tests ausführen
run: npm test -- --coverage
- name: Build erstellen
run: npm run build
- name: Coverage-Report hochladen
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
Der Schritt npm ci ist dabei gegenüber npm install zu bevorzugen, da er strikt die Lockfile befolgt und reproduzierbare Builds garantiert. Das integrierte Caching über cache: 'npm' in setup-node spart wertvolle Sekunden, indem es den ~/.npm-Cache zwischen Runs teilt.
Das Schlüsselwort if: always() sorgt dafür, dass der Coverage-Upload selbst dann erfolgt, wenn vorherige Steps fehlgeschlagen sind – so gehen wertvolle Diagnosedaten nicht verloren. Für die Abdeckung ganzer Test-Suiten empfiehlt sich die parallele Ausführung in Matrix-Jobs, die wir später behandeln.
Eine der leistungsstärksten Funktionen von GitHub Actions sind Matrix-Builds. Sie ermöglichen es, denselben Job mehrfach mit variierenden Parametern auszuführen, ohne den Workflow-Code zu duplizieren. Dies ist ideal, um eine Anwendung gegen mehrere Node-Versionen, Betriebssysteme oder Browser zu testen.
Im folgenden Beispiel erstellen wir eine Matrix, die unsere Tests unter Ubuntu, macOS und Windows mit Node.js 18, 20 und 22 ausführt – insgesamt neun Kombinationen, die parallel laufen. GitHub erstellt automatisch einen eigenen Runner pro Matrix-Kombination und fasst die Ergebnisse übersichtlich zusammen.
jobs:
test:
name: Tests auf ${{ matrix.os }} mit Node ${{ matrix.node }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [18, 20, 22]
steps:
- uses: actions/checkout@v5
- name: Node.js ${{ matrix.node }} einrichten
uses: actions/setup-node@v5
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- run: npm ci
- run: npm test
Die Option fail-fast: false ist entscheidend: Sie sorgt dafür, dass alle Matrix-Kombinationen ausgeführt werden, auch wenn eine fehlschlägt. So erhältst du einen vollständigen Überblick über Kompatibilitätsprobleme, anstatt beim ersten Fehler abgebrochen zu werden.
Mit Matrix-Extensions kannst du dynamische Konfigurationen erstellen. So lassen sich include und exclude nutzen, um spezifische Kombinationen hinzuzufügen oder auszuschließen – etwa um Windows + Node 18 auszulassen, wenn

Praxisnaher Guide für Docker Compose auf dem VPS: Webserver, Datenbank, Reverse Proxy, TLS, Backups, Updates und Sicherheit richtig planen und betreiben.