refactor(deploy): Image-Versionen fest in Dockerfiles verankern
ARG-Variablen durch feste Werte in FROM ersetzt — nicht per .env ueberschreibbar. PYTHON_VERSION, NODE_VERSION, NPM_VERSION, NGINX_VERSION aus .env, env-sample und Compose-Dateien entfernt. Deployment-Anleitung erstellt und entsprechend angepasst. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
1 parent
3b3e2893e5
commit
40ad0e1ba9
6 files changed
+429
-32
No files matched your search
@@ -0,0 +1,422 @@
|
||||
# Anleitung: Automatisches Deployment einrichten
|
||||
|
||||
Diese Anleitung richtet sich an den Administrator des Deploy-Servers.
|
||||
Sie beschreibt, wie der automatische Deploy-Mechanismus fuer KB-CRM
|
||||
eingerichtet und betrieben wird.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architektur ueberblick
|
||||
|
||||
```
|
||||
Entwickler
|
||||
│ git push origin main
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Git-Remote │ (z.B. Gitea auf git.everdc.eu)
|
||||
└────────┬────────┘
|
||||
│ Webhook oder post-receive Hook
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Deploy-Server │
|
||||
│ (Deploy-Script) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌──────────┴──────────┐
|
||||
▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Stufe 1: TEST │ │ Stufe 2: PROD │
|
||||
│ (automatisch) │ │ (manuell) │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
**Prinzip:**
|
||||
- Jeder `git push` auf `main` loest automatisch ein Deployment auf dem
|
||||
Test-Server aus (Stufe 1).
|
||||
- Nach erfolgreicher Verifikation wird manuell auf den Prod-Server
|
||||
deployt (Stufe 2).
|
||||
- In Prod wird der gesamte Code (Python + TypeScript) in das Docker-Image
|
||||
gebaut. Es wird kein Node.js, npm oder Python-venv auf dem Server benoetigt.
|
||||
- Der Deploy-Server benoetigt nur: `git`, `docker` und `docker compose`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Voraussetzungen auf dem Deploy-Server
|
||||
|
||||
Folgende Software muss installiert sein:
|
||||
|
||||
| Software | Version | Zweck |
|
||||
|---|---|---|
|
||||
| `git` | aktuell | Code vom Remote-Repository holen |
|
||||
| `docker` | aktuell | Container bauen und starten |
|
||||
| `docker compose` | v2+ | Multi-Container-Orchestrierung |
|
||||
| `curl` | aktuell | Health-Check nach Deploy |
|
||||
|
||||
Docker Compose muss als Plugin installiert sein (Befehl: `docker compose`,
|
||||
nicht `docker-compose`).
|
||||
|
||||
---
|
||||
|
||||
## 3. Verzeichnisstruktur auf dem Deploy-Server
|
||||
|
||||
Es werden zwei Umgebungen (test-prod und prod) parallel betrieben:
|
||||
|
||||
```
|
||||
/opt/kbcrm/
|
||||
├── test-prod/
|
||||
│ ├── repo/ ← git clone des Repos
|
||||
│ └── .env ← test-prod Umgebung (eigene Ports, eigene DB)
|
||||
├── prod/
|
||||
│ ├── repo/
|
||||
│ └── .env ← prod Umgebung
|
||||
└── scripts/
|
||||
├── deploy-kbcrm-test.sh ← aus dem Repo (scripts/)
|
||||
└── deploy-kbcrm-prod.sh ← aus dem Repo (scripts/)
|
||||
```
|
||||
|
||||
Die SQLite-Datenbanken liegen ausserhalb des Repos in einem bind-mount
|
||||
(`PYTHON_DB_DIR`), der beim Deploy nicht beruehrt wird.
|
||||
|
||||
---
|
||||
|
||||
## 4. Einrichtung: Schritt fuer Schritt
|
||||
|
||||
### 4.1. Repositories klonen
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/kbcrm/test-prod /opt/kbcrm/prod
|
||||
|
||||
# Test-Prod Repository
|
||||
sudo git clone https://git.everdc.eu/chmln-app-dev/kbcrm /opt/kbcrm/test-prod/repo
|
||||
|
||||
# Prod Repository
|
||||
sudo git clone https://git.everdc.eu/chmln-app-dev/kbcrm /opt/kbcrm/prod/repo
|
||||
```
|
||||
|
||||
### 4.2. `.env`-Dateien anlegen
|
||||
|
||||
Kopieren Sie die Vorlage aus dem Repo und passen Sie die Werte an:
|
||||
|
||||
```bash
|
||||
# Test-Prod
|
||||
cp /opt/kbcrm/test-prod/repo/env-sample /opt/kbcrm/test-prod/.env
|
||||
|
||||
# Prod
|
||||
cp /opt/kbcrm/prod/repo/env-sample /opt/kbcrm/prod/.env
|
||||
```
|
||||
|
||||
### 4.3. `.env` fuer Test-Prod anpassen
|
||||
|
||||
```bash
|
||||
vi /opt/kbcrm/test-prod/.env
|
||||
```
|
||||
|
||||
Folgende Einstellungen muessen angepasst werden:
|
||||
|
||||
```bash
|
||||
# WICHTIG: BUILD_ENVIRONMENT muss in den .env-Dateien auf dem Deploy-Server
|
||||
# NICHT gesetzt werden. Die Deploy-Scripts rufen docker compose explizit
|
||||
# mit -f docker-compose.prod.yaml auf und ignorieren COMPOSE_FILE.
|
||||
# Daher kann BUILD_ENVIRONMENT und COMPOSE_FILE aus der .env geloescht
|
||||
# oder ignoriert werden.
|
||||
|
||||
# NGINX-Server
|
||||
NGINX_USE_SSL=true
|
||||
NGINX_HOST_PORT=8443 # eigener Port fuer Test-Prod
|
||||
NGINX_SERVER_NAME=test.kbp_crm.mylocal.de
|
||||
# NGINX_STATIC_DIR und NGINX_CONFIG_TEMPLATE_DIR werden in Prod nicht
|
||||
# benoetigt (statische Dateien und Templates sind im Image).
|
||||
NGINX_CERTS=/opt/kbcrm/test-prod/certs # Pfad zu SSL-Zertifikaten
|
||||
NGINX_CERT=test-wildcard.mylocal.crt
|
||||
NGINX_CERT_KEY=test-wildcard.mylocal.key
|
||||
|
||||
# Python App-Server
|
||||
PYTHON_DB_DIR=/opt/kbcrm/test-prod/data # eigene DB fuer Test-Prod
|
||||
|
||||
|
||||
# OIDC-Settings anpassen (ggf. separater OIDC-Client fuer Test)
|
||||
ZITADEL_ISSUER=https://id.vmlx.de
|
||||
ZITADEL_CLIENT_ID=<test-client-id>
|
||||
ZITADEL_CLIENT_SECRET=<test-client-secret>
|
||||
ZITADEL_REDIRECT_URI=https://test.kbp_crm.mylocal.de/auth/callback
|
||||
```
|
||||
|
||||
### 4.4. `.env` fuer Prod anpassen
|
||||
|
||||
```bash
|
||||
vi /opt/kbcrm/prod/.env
|
||||
```
|
||||
|
||||
```bash
|
||||
NGINX_HOST_PORT=443 # Produktions-Port
|
||||
NGINX_SERVER_NAME=kbp_crm.mylocal.de
|
||||
NGINX_CERTS=/opt/kbcrm/prod/certs
|
||||
NGINX_CERT=wildcard.mylocal.crt
|
||||
NGINX_CERT_KEY=wildcard.mylocal.key
|
||||
|
||||
PYTHON_DB_DIR=/opt/kbcrm/prod/data # eigene DB fuer Prod
|
||||
|
||||
ZITADEL_REDIRECT_URI=https://kbp_crm.mylocal.de/auth/callback
|
||||
```
|
||||
|
||||
### 4.5. Datenbank-Verzeichnisse erstellen
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/kbcrm/test-prod/data
|
||||
sudo mkdir -p /opt/kbcrm/prod/data
|
||||
```
|
||||
|
||||
### 4.6. SSL-Zertifikate ablegen
|
||||
|
||||
Kopieren Sie die Zertifikate in die in `.env` angegebenen Verzeichnisse:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/kbcrm/test-prod/certs /opt/kbcrm/prod/certs
|
||||
sudo cp wildcard.mylocal.crt wildcard.mylocal.key /opt/kbcrm/test-prod/certs/
|
||||
sudo cp wildcard.mylocal.crt wildcard.mylocal.key /opt/kbcrm/prod/certs/
|
||||
```
|
||||
|
||||
### 4.7. Deploy-Scripts kopieren
|
||||
|
||||
Die Scripts liegen im Repo unter `scripts/`. Kopieren Sie sie an einen
|
||||
zentralen Ort:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/kbcrm/scripts
|
||||
sudo cp /opt/kbcrm/test-prod/repo/scripts/deploy-kbcrm-test.sh /opt/kbcrm/scripts/
|
||||
sudo cp /opt/kbcrm/prod/repo/scripts/deploy-kbcrm-prod.sh /opt/kbcrm/scripts/
|
||||
sudo chmod +x /opt/kbcrm/scripts/*.sh
|
||||
```
|
||||
|
||||
Passen Sie die Pfad-Variablen am Anfang der Scripts an, falls Ihre
|
||||
Verzeichnisstruktur abweicht.
|
||||
|
||||
---
|
||||
|
||||
## 5. Git-Hook einrichten (automatisches Test-Deploy)
|
||||
|
||||
### Variante A: post-receive Hook (direkt auf dem Git-Server)
|
||||
|
||||
Wenn Shell-Zugang zum Git-Server besteht:
|
||||
|
||||
```bash
|
||||
# Auf dem Git-Server, im bare Repository:
|
||||
vi /srv/git/kbcrm.git/hooks/post-receive
|
||||
```
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
while read oldrev newrev ref; do
|
||||
if [ "$ref" = "refs/heads/main" ]; then
|
||||
ssh deploy-user@deploy-server "/opt/kbcrm/scripts/deploy-kbcrm-test.sh"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
```bash
|
||||
chmod +x /srv/git/kbcrm.git/hooks/post-receive
|
||||
```
|
||||
|
||||
### Variante B: Webhook (empfohlen fuer Gitea)
|
||||
|
||||
1. In Gitea: Repository-Einstellungen -> Webhooks -> Webhook hinzufuegen
|
||||
2. URL: `http://deploy-server:9000/webhook` (Beispiel)
|
||||
3. Content-Type: `application/json`
|
||||
4. Trigger: "Push Events" (nur auf `main`)
|
||||
5. Auf dem Deploy-Server: kleiner HTTP-Listener, der den Webhook entgegennimmt
|
||||
und das Deploy-Script startet.
|
||||
|
||||
Beispiel fuer einen einfachen Webhook-Listener (systemd-Service mit Python):
|
||||
|
||||
```python
|
||||
# /opt/kbcrm/scripts/webhook-listener.py
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
import subprocess
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
subprocess.run(["/opt/kbcrm/scripts/deploy-kbcrm-test.sh"])
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
|
||||
HTTPServer(("", 9000), Handler).serve_forever()
|
||||
```
|
||||
|
||||
Systemd-Service:
|
||||
|
||||
```ini
|
||||
# /etc/systemd/system/kbcrm-webhook.service
|
||||
[Unit]
|
||||
Description=KB-CRM Deploy Webhook Listener
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python3 /opt/kbcrm/scripts/webhook-listener.py
|
||||
Restart=always
|
||||
User=deploy-user
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now kbcrm-webhook
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Deployment durchfuehren
|
||||
|
||||
### 6.1. Automatisches Deploy nach Test-Prod
|
||||
|
||||
Wird durch `git push` ausgeloest (sofern Hook eingerichtet). Manuell:
|
||||
|
||||
```bash
|
||||
/opt/kbcrm/scripts/deploy-kbcrm-test.sh
|
||||
```
|
||||
|
||||
Das Script fuehrt folgende Schritte aus:
|
||||
1. `git pull` (latest main)
|
||||
2. `docker compose up -d --build` (baut beide Images: NGINX mit TypeScript-
|
||||
Build und Python mit Anwendungscode)
|
||||
3. Health-Check
|
||||
|
||||
### 6.2. Manuelle Promotion nach Prod
|
||||
|
||||
Nach Verifikation auf dem Test-Server:
|
||||
|
||||
```bash
|
||||
/opt/kbcrm/scripts/deploy-kbcrm-prod.sh
|
||||
```
|
||||
|
||||
Das Script fragt eine Bestaetigung ("yes/no") und fuehrt dann den gleichen
|
||||
Ablauf aus wie das Test-Script, jedoch mit der Prod-`.env`.
|
||||
|
||||
### 6.3. Alternative: Git-Tag-basierte Promotion
|
||||
|
||||
Statt das Prod-Script manuell aufzurufen, kann ein Git-Tag das Prod-Deploy
|
||||
ausloesen:
|
||||
|
||||
```bash
|
||||
# Auf dem Entwickler-Rechner:
|
||||
git tag -a v00.00.02 -m "Release: deploy to prod"
|
||||
git push origin v00.00.02
|
||||
```
|
||||
|
||||
Der `post-receive`-Hook prueft auf Tags:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
while read oldrev newrev ref; do
|
||||
if [ "$ref" = "refs/heads/main" ]; then
|
||||
ssh deploy-user@deploy-server "/opt/kbcrm/scripts/deploy-kbcrm-test.sh"
|
||||
elif [[ "$ref" = refs/tags/v* ]]; then
|
||||
ssh deploy-user@deploy-server "/opt/kbcrm/scripts/deploy-kbcrm-prod.sh"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Wartung und Fehlersuche
|
||||
|
||||
### Logs anzeigen
|
||||
|
||||
```bash
|
||||
# Test-Prod
|
||||
docker compose --env-file /opt/kbcrm/test-prod/.env \
|
||||
-f /opt/kbcrm/test-prod/repo/docker-compose.prod.yaml logs
|
||||
|
||||
# Prod
|
||||
docker compose --env-file /opt/kbcrm/prod/.env \
|
||||
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml logs
|
||||
|
||||
# Nur Python-Container
|
||||
docker compose --env-file /opt/kbcrm/prod/.env \
|
||||
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml logs pythonapp
|
||||
|
||||
# Nur NGINX-Container
|
||||
docker compose --env-file /opt/kbcrm/prod/.env \
|
||||
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml logs nginx-proxy
|
||||
```
|
||||
|
||||
### Container-Status pruefen
|
||||
|
||||
```bash
|
||||
docker compose --env-file /opt/kbcrm/prod/.env \
|
||||
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml ps
|
||||
```
|
||||
|
||||
### Manuell in den Container wechseln
|
||||
|
||||
```bash
|
||||
docker compose --env-file /opt/kbcrm/prod/.env \
|
||||
-f /opt/kbcrm/prod/repo/docker-compose.prod.yaml exec pythonapp bash
|
||||
```
|
||||
|
||||
### Rollback
|
||||
|
||||
Bei Problemen kann auf einen frueheren Stand zurueckgekehrt werden:
|
||||
|
||||
```bash
|
||||
# Auf dem Deploy-Server:
|
||||
cd /opt/kbcrm/prod/repo
|
||||
git log --oneline -10 # frueheren Commit finden
|
||||
git checkout <commit-hash>
|
||||
docker compose --env-file /opt/kbcrm/prod/.env \
|
||||
-f docker-compose.prod.yaml up -d --build
|
||||
```
|
||||
|
||||
### Datenbank sichern
|
||||
|
||||
Die SQLite-Datenbanken liegen im bind-mount (`PYTHON_DB_DIR`).
|
||||
Sicherung:
|
||||
|
||||
```bash
|
||||
cp /opt/kbcrm/prod/data/*.db /backup/kbcrm-prod-$(date +%Y%m%d).db
|
||||
```
|
||||
|
||||
### Docker-Images aufraeumen
|
||||
|
||||
Nach mehreren Deploys koennen alte Images Speicher belegen:
|
||||
|
||||
```bash
|
||||
docker image prune -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Uebersicht: `.env`-Variablen fuer Prod
|
||||
|
||||
| Variable | Erforderlich | Beschreibung |
|
||||
|---|---|---|
|
||||
| `NGINX_USE_SSL` | ja | SSL aktivieren (true/false) |
|
||||
| `NGINX_HOST_PORT` | ja | Externer Port (443 fuer SSL, 8080 fuer no-SSL) |
|
||||
| `NGINX_SERVER_NAME` | ja | Server-Name fuer NGINX-Konfiguration |
|
||||
| `NGINX_CERTS` | ja | Pfad zu SSL-Zertifikaten (bind-mount) |
|
||||
| `NGINX_CERT` | ja | Zertifikatsdatei |
|
||||
| `NGINX_CERT_KEY` | ja | Privater Schluessel |
|
||||
| `NGINX_STATIC_DIR` | nein | Nur in Dev; in Prod im Image |
|
||||
| `NGINX_CONFIG_TEMPLATE_DIR` | nein | Nur in Dev; in Prod im Image |
|
||||
| `PYTHON_DB_DIR` | ja | Pfad zu SQLite-Datenbanken (bind-mount) |
|
||||
| `PYTHON_DEV_DIR` | nein | Nur in Dev |
|
||||
| `APP_DEBUG` | nein | Nur in Dev; in Prod nicht setzen |
|
||||
| `BUILD_ENVIRONMENT` | nein | Nicht relevant — Deploy-Scripts geben Compose-Datei explizit an. In .env auf Deploy-Server nicht erforderlich |
|
||||
| `ZITADEL_*` | ja | OIDC-Konfiguration |
|
||||
| `COMPOSE_FILE` | nein | Wird von Deploy-Scripts ignoriert |
|
||||
|
||||
---
|
||||
|
||||
## 9. Checkliste fuer den Admin
|
||||
|
||||
- [ ] Docker und Docker Compose installiert
|
||||
- [ ] Git installiert, Repository geklont (test-prod + prod)
|
||||
- [ ] `.env`-Dateien erstellt und angepasst (Ports, DB, Zertifikate, OIDC)
|
||||
- [ ] Datenbank-Verzeichnisse erstellt (`PYTHON_DB_DIR`)
|
||||
- [ ] SSL-Zertifikate abgelegt (`NGINX_CERTS`)
|
||||
- [ ] Deploy-Scripts kopiert und ausfuehrbar gemacht
|
||||
- [ ] Git-Hook oder Webhook eingerichtet (fuer automatisches Test-Deploy)
|
||||
- [ ] Erster manueller Deploy-Test: `deploy-kbcrm-test.sh`
|
||||
- [ ] Health-Check erfolgreich: `curl -k https://localhost:8443/health-check`
|
||||
- [ ] Erster Prod-Deploy: `deploy-kbcrm-prod.sh`
|
||||
- [ ] Health-Check erfolgreich: `curl -k https://localhost:443/health-check`
|
||||
Reference in new issue
Block a user