docs: vollständige Dokumentation (Dokploy-Deployment, Auto-Deploy, Troubleshooting, Architektur)
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# Auto-Deploy-Pipeline
|
||||
|
||||
Ziel: **`git push` = neue Version automatisch live**, ohne manuellen Eingriff.
|
||||
|
||||
## Überblick
|
||||
|
||||
```
|
||||
Code ändern → git push (Gitea) → ┬─ Webhook → Hermes-Receiver → SSH → Dokploy → Build + Deploy
|
||||
└─ Cron-Polling (alle 2 Min) → Dokploy → Build + Deploy
|
||||
```
|
||||
|
||||
Es gibt **zwei unabhängige Trigger**, weil der Gitea-Webhook unzuverlässig ist (siehe
|
||||
[„Warum zwei Trigger?"](#warum-zwei-trigger)):
|
||||
|
||||
| Mechanismus | Latenz | Zuverlässigkeit |
|
||||
|-------------|--------|-----------------|
|
||||
| Gitea-Webhook → Receiver | ~5 s | ⚠️ sporadisch |
|
||||
| Cron-Polling | ≤ 2 min | ✅ garantiert |
|
||||
|
||||
---
|
||||
|
||||
## Komponenten
|
||||
|
||||
### 1. Gitea-Webhook
|
||||
|
||||
Per Gitea-API erstellt:
|
||||
|
||||
```bash
|
||||
curl -X POST "https://git.kgessner.de/api/v1/repos/LuiiCode/techno-todo/hooks" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "gitea",
|
||||
"config": {"url": "http://192.168.0.80:8002/hook", "content_type": "json"},
|
||||
"events": ["push"],
|
||||
"active": true
|
||||
}'
|
||||
```
|
||||
|
||||
Zeigt auf den Webhook-Receiver auf dem Hermes-Server (`192.168.0.80:8002`).
|
||||
|
||||
### 2. Webhook-Receiver (Hermes)
|
||||
|
||||
Datei: `/home/hermes/webhook-receiver.py`
|
||||
|
||||
- Python-Stdlib-`http.server` (keine Dependencies)
|
||||
- Lauscht auf `0.0.0.0:8002`
|
||||
- Bei `X-Gitea-Event: push` auf `refs/heads/main` des Ziel-Repos:
|
||||
- startet **asynchron** (Thread) `ssh root@192.168.0.184 /opt/deploy-techno-todo.sh`
|
||||
- antwortet sofort mit `200` (Gitea wartet nicht auf den Deploy)
|
||||
- Loggt in `/home/hermes/webhook-receiver.log`
|
||||
|
||||
### 3. Deploy-Skript (Dokploy-Host)
|
||||
|
||||
Datei: `/opt/deploy-techno-todo.sh`
|
||||
|
||||
**Idempotent** — deployt nur, wenn es neue Commits gibt:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
REPO_DIR="/opt/repos/techno-todo"
|
||||
SERVICE_NAME="techno-todo-v2-mzs9mj"
|
||||
cd "$REPO_DIR"
|
||||
|
||||
git fetch --all --prune >/dev/null 2>&1
|
||||
LOCAL=$(git rev-parse HEAD)
|
||||
REMOTE=$(git rev-parse origin/main)
|
||||
[ "$LOCAL" = "$REMOTE" ] && { echo "UP-TO-DATE: $LOCAL"; exit 0; }
|
||||
|
||||
git reset --hard origin/main
|
||||
COMMIT=$(git rev-parse --short HEAD)
|
||||
docker build -t "techno-todo:${COMMIT}" .
|
||||
docker tag "techno-todo:${COMMIT}" techno-todo:latest
|
||||
docker service update --force --image "techno-todo:${COMMIT}" "$SERVICE_NAME"
|
||||
echo "DONE: deployed ${COMMIT}"
|
||||
```
|
||||
|
||||
Das Repo liegt persistent unter `/opt/repos/techno-todo` auf dem Dokploy-Host.
|
||||
|
||||
### 4. Cron-Polling (Fallback)
|
||||
|
||||
Auf dem Dokploy-Host:
|
||||
|
||||
```bash
|
||||
*/2 * * * * /opt/deploy-techno-todo.sh >> /var/log/techno-todo-deploy.log 2>&1
|
||||
```
|
||||
|
||||
Da das Skript idempotent ist, passiert bei „keine neuen Commits" nichts (exit 0).
|
||||
|
||||
---
|
||||
|
||||
## Warum zwei Trigger?
|
||||
|
||||
Der Gitea-Webhook erwies sich beim POC als **unzuverlässig**: Von mehreren Pushes wurden
|
||||
nur einige ausgelöst, andere gingen verloren.
|
||||
|
||||
**Root-Cause:** Gitea läuft in einem **Kubernetes-Cluster (Talos)** auf Proxmox — also in
|
||||
einem anderen Netzwerk-Kontext als der Dokploy-Docker-Swarm-Host (`192.168.0.184`) und der
|
||||
Hermes-Server (`192.168.0.80`). Ausgehende Verbindungen aus dem K8s-Cluster zu internen
|
||||
`192.168.0.x`-Adressen sind nicht zuverlässig möglich (CNI/NAT-Isolation).
|
||||
|
||||
Der Cron-Polling-Fallback umgeht das komplett: Er läuft direkt **auf** dem Dokploy-Host und
|
||||
holt sich den Git-Stand aktiv ab, statt auf einen eingehenden Webhook zu warten.
|
||||
|
||||
---
|
||||
|
||||
## Setup-Reihenfolge (für eine neue App)
|
||||
|
||||
1. Repo persistent auf Dokploy klonen: `/opt/repos/<app>`
|
||||
2. Deploy-Skript anpassen (Repo-Dir + Service-Name) → `/opt/deploy-<app>.sh`
|
||||
3. Cron-Job auf Dokploy einrichten (alle 2 Min)
|
||||
4. (Optional) Webhook-Receiver auf Hermes starten + Gitea-Webhook einrichten
|
||||
|
||||
## Verifikation
|
||||
|
||||
```bash
|
||||
# 1. Push machen
|
||||
git push
|
||||
|
||||
# 2. Nach ~2 Min prüfen:
|
||||
ssh root@192.168.0.184 "docker service ls --format '{{.Name}} {{.Image}}' | grep techno"
|
||||
# → techno-todo-v2-mzs9mj techno-todo:<neuer-commit>
|
||||
|
||||
# 3. Live testen:
|
||||
curl -H "Host: techno-todo.192.168.0.184.sslip.io" http://192.168.0.184/
|
||||
```
|
||||
Reference in New Issue
Block a user