Automatisches Deployment mit GitHub Actions: CI/CD Pipeline Einrichtung
CI/CD-Pipelines mit GitHub Actions erstellen: Docker Build und Push, SSH-Server-Deployment, Test-Automatisierung, Secrets-Verwaltung und Workflow-Optimierung.
Inhaltsverzeichnis
Automatisches Deployment mit GitHub Actions: CI/CD Pipeline Einrichtung
GitHub Actions ist eine leistungsstarke CI/CD-Plattform, die Code-Änderungen automatisch testet, baut und auf dem Server deployt. In diesem Leitfaden bauen wir eine produktionsreife Pipeline von Grund auf.
Was ist GitHub Actions?
GitHub Actions ist eine in GitHub-Repositories integrierte Automatisierungsplattform:
- Reagiert auf Ereignisse wie Push, PR und Schedule
- Führt parallele und sequentielle Workflows aus
- 2.000 Minuten/Monat kostenlos (unbegrenzt für öffentliche Repos)
- Erweiterbar mit Tausenden von fertigen Actions
GitHub Actions Workflow-Dateien werden im YAML-Format im Verzeichnis .github/workflows/ gespeichert.
Grundlegende Workflow-Struktur
# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Node.js einrichten
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Abhängigkeiten installieren
run: npm ci
- name: Tests ausführen
run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deployen
run: echo "Deploy-Schritte hier"
on / jobs / steps Struktur
Trigger (on)
on:
# Push auf Branch
push:
branches: [main, develop]
paths:
- 'src/**'
- 'package.json'
# Pull Request
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
# Geplante Ausführung (cron)
schedule:
- cron: '0 2 * * *' # Jede Nacht um 02:00
# Manueller Trigger
workflow_dispatch:
inputs:
environment:
description: 'Deploy-Umgebung'
required: true
default: 'staging'
type: choice
options: [staging, production]
# Wenn ein anderer Workflow abgeschlossen ist
workflow_run:
workflows: ["Build"]
types: [completed]
Job-Konfiguration
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: test
timeout-minutes: 30
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
Docker Build und Push
Push zu Docker Hub
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker-Metadaten
id: meta
uses: docker/metadata-action@v5
with:
images: benutzername/meine-app
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha,prefix=sha-
- name: Docker Buildx einrichten
uses: docker/setup-buildx-action@v3
- name: Bei Docker Hub anmelden
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build und Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
GitHub Container Registry (GHCR)
- name: Bei GHCR anmelden
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build und Push (GHCR)
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
SSH-Deployment auf Server
Verwendung von appleboy/ssh-action
deploy:
needs: docker
runs-on: ubuntu-latest
environment: production
steps:
- name: Deployment via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SERVER_PORT }}
script: |
cd /root/meine-app
git pull origin main
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
echo "Deployment abgeschlossen: $(date)"
Deployment mit Docker Compose
- name: Docker Compose Deployment
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# Neues Image ziehen
docker pull ghcr.io/${{ github.repository }}:latest
# Zero-Downtime-Deployment
docker compose -f /root/app/docker-compose.yml up -d \
--no-deps \
--build \
--remove-orphans
# Alte Images bereinigen
docker image prune -af --filter "until=24h"
# Health Check
sleep 10
curl -f http://localhost:3000/health || exit 1
Secrets-Verwaltung
GitHub Secrets speichert sensible Informationen sicher:
steps:
- name: Anwendungskonfiguration
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
API_KEY: ${{ secrets.API_KEY }}
run: |
echo "Konfiguration geladen"
# Secrets werden nie in Logs ausgegeben, automatisch maskiert
Erforderliche Secrets:
SERVER_HOST: Server-IP-AdresseSERVER_USER: SSH-BenutzernameSSH_PRIVATE_KEY: Privater SSH-SchlüsselDOCKERHUB_USERNAME: Docker Hub BenutzernameDOCKERHUB_TOKEN: Docker Hub Zugriffstoken
Cache-Nutzung
- name: Node.js-Abhängigkeiten cachen
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: npm ci (gecacht)
run: npm ci
# Docker Layer Cache
- name: Build und Push
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
Matrix Builds
jobs:
test:
strategy:
fail-fast: false
matrix:
node: [18, 20]
os: [ubuntu-latest, macos-latest]
include:
- node: 20
os: ubuntu-latest
coverage: true
exclude:
- node: 18
os: macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
- name: Coverage-Bericht
if: matrix.coverage
run: npm run coverage
Environment Protection Rules
jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: Production-Deployment
run: echo "Deployment in Production"
In GitHub unter Settings > Environments > production:
- Required reviewers (Genehmigung erforderlich)
- Wait timer (Wartezeit)
- Deployment branches (nur main)
Vollständiges CI/CD Pipeline Beispiel
name: Full CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test -- --coverage
- name: Coverage hochladen
uses: codecov/codecov-action@v4
build:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- uses: docker/build-push-action@v5
with:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://example.com
steps:
- uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
docker compose -f /root/app/docker-compose.yml up -d
docker image prune -f
Fazit
Durch die Einrichtung einer vollautomatischen CI/CD-Pipeline mit GitHub Actions können Sie die Codequalität verbessern, Deployment-Fehler reduzieren und Ihren Entwicklungsprozess beschleunigen. Mit Secrets-Verwaltung, Cache-Optimierung und Environment Protection Rules erhalten Sie eine produktionsreife Pipeline.
Verwandte Artikel
Docker Compose Leitfaden: Verwaltung von Multi-Container-Anwendungen
Multi-Container-Anwendungen mit Docker Compose definieren und verwalten: Service-Abhängigkeiten, Umgebungsvariablen, Health Checks, Skalierung und Production-Deployment. Umfassender Leitfaden.
Server-Automatisierung mit Ansible: Infrastructure as Code
Ansible-Installation, Inventory-Datei, Playbook-Erstellung, Rollenstruktur, Variablen, verschlüsselter Vault, Ad-hoc-Befehle und Server-Konfigurationsautomatisierung. Schritt-für-Schritt-Anleitung.
Caddy Web Server Einrichtung: Automatisches HTTPS und Reverse Proxy
Caddy Web Server Installation, Caddyfile-Konfiguration, automatisches Let's Encrypt SSL, Reverse Proxy, Static Site Hosting, PHP-FPM-Integration und Performance-Einstellungen.