Docker Compose Leitfaden: Verwaltung von Multi-Container-Anwendungen
Multi-Container-Anwendungen mit Docker Compose definieren: Service-Abhängigkeiten, Umgebungsvariablen, Health Checks, Skalierung und Production-Deployment.
CI/CD-Pipelines mit GitHub Actions erstellen: Docker Build und Push, SSH-Server-Deployment, Test-Automatisierung, Secrets-Verwaltung und Workflow-Optimierung.
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.
GitHub Actions ist eine in GitHub-Repositories integrierte Automatisierungsplattform:
GitHub Actions Workflow-Dateien werden im YAML-Format im Verzeichnis .github/workflows/ gespeichert.
# .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:
# 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]
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 }}
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
- 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
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)"
- 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
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 - 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
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
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:
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
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.
Für öffentliche Repositories vollständig kostenlos und unbegrenzt. Private Repositories erhalten 2.000 kostenlose Minuten pro Monat. Wenn dieses Limit beim GitHub Free-Plan überschritten wird, pausieren Workflows. GitHub Pro und Team-Pläne beinhalten mehr Minuten.
Erstellen Sie ein Schlüsselpaar auf Ihrem lokalen Rechner mit 'ssh-keygen -t ed25519 -C "github-actions"'. Fügen Sie den Public Key (~/.ssh/id_ed25519.pub) zu ~/.ssh/authorized_keys auf Ihrem Server hinzu. Speichern Sie den Private Key (~/.ssh/id_ed25519) in Ihrem GitHub-Repo unter Settings > Secrets als SSH_PRIVATE_KEY.
'needs: test' bedeutet, dass dieser Job erst ausgeführt wird, wenn der 'test'-Job erfolgreich abgeschlossen ist. Verwenden Sie 'needs: [test, build]' für mehrere Abhängigkeiten. Wenn ein Job fehlschlägt, werden abhängige Jobs automatisch abgebrochen.
Ja, verwenden Sie 'on.push.paths', um bestimmte Dateien oder Verzeichnisse zu überwachen. Zum Beispiel löst 'paths: ["src/**", "package.json"]' den Workflow nur aus, wenn diese Dateien geändert werden. Verwenden Sie 'paths-ignore', um bestimmte Dateien auszuschließen.
Docker Build Cache verhindert das Neuerstellen unveränderter Schichten. 'cache-from: type=gha' verwendet den GitHub Actions Cache. Dies kann die Build-Zeit um 50-80% reduzieren. Es macht besonders bei Abhängigkeits-Installationsschritten (npm install, pip install) einen großen Unterschied.
Sie fügen einen Genehmigungsmechanismus für kritische Umgebungen wie Production hinzu. Mit 'Required reviewers' kann ohne Genehmigung bestimmter Personen kein Deployment durchgeführt werden. 'Wait timer' legt eine Wartezeit vor dem Deployment fest. Dies verhindert versehentliche Deployments in Production.
Multi-Container-Anwendungen mit Docker Compose definieren: Service-Abhängigkeiten, Umgebungsvariablen, Health Checks, Skalierung und Production-Deployment.
Ansible Schritt für Schritt: Installation, Inventory, Playbooks, Rollen, Variablen, verschlüsselter Vault, Ad-hoc-Befehle und Serverautomatisierung.
Caddy-Webserver installieren: Caddyfile-Konfiguration, automatisches Let's Encrypt SSL, Reverse Proxy, statische Websites, PHP-FPM-Integration und Tuning.