Merge feature/auto-deploy: automatisches Deployment und Start-Meldungen
This commit is contained in:
commit
bde45871f6
16 files changed
+638
-110
No files matched your search
@@ -0,0 +1,8 @@
|
|||||||
|
.git/
|
||||||
|
Client/node_modules/
|
||||||
|
Client/tsout/
|
||||||
|
App_Server/data/
|
||||||
|
App_Server/env/
|
||||||
|
oidc-test/
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
+22
-23
@@ -1,7 +1,8 @@
|
|||||||
ARG PYTHON_VERSION
|
# ── Stage: prod ──────────────────────────────────────────────────
|
||||||
ARG NODE_VERSION
|
# Build-Context ist das Repo-Root (.), daher muessen alle COPY-Pfade
|
||||||
ARG NPM_VERSION
|
# mit App_Server/ praefigiert werden.
|
||||||
FROM python:${PYTHON_VERSION} AS prod
|
# Python-Version fest im Dockerfile verankert — nicht per .env ueberschreibbar.
|
||||||
|
FROM python:slim-bookworm AS prod
|
||||||
RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
||||||
RUN apt-get clean && apt-get update && apt-get install -y locales
|
RUN apt-get clean && apt-get update && apt-get install -y locales
|
||||||
RUN echo "de_DE.UTF-8 UTF-8" >> /etc/locale.gen
|
RUN echo "de_DE.UTF-8 UTF-8" >> /etc/locale.gen
|
||||||
@@ -12,18 +13,21 @@ RUN locale-gen
|
|||||||
RUN mkdir -p /usr/opt/pythonapp/App_Server/root /usr/opt/pythonapp/env /usr/var/pythonappdata
|
RUN mkdir -p /usr/opt/pythonapp/App_Server/root /usr/opt/pythonapp/env /usr/var/pythonappdata
|
||||||
WORKDIR /usr/opt/pythonapp
|
WORKDIR /usr/opt/pythonapp
|
||||||
RUN python -m venv --upgrade-deps /usr/opt/pythonapp/env
|
RUN python -m venv --upgrade-deps /usr/opt/pythonapp/env
|
||||||
COPY root/requirements.txt /usr/opt/pythonapp/App_Server/root/requirements.txt
|
COPY App_Server/root/requirements.txt /usr/opt/pythonapp/App_Server/root/requirements.txt
|
||||||
RUN /usr/opt/pythonapp/env/bin/pip install --no-cache-dir --upgrade pip -r /usr/opt/pythonapp/App_Server/root/requirements.txt
|
RUN /usr/opt/pythonapp/env/bin/pip install --no-cache-dir --upgrade pip -r /usr/opt/pythonapp/App_Server/root/requirements.txt
|
||||||
# COPY scripts/init.sh /init.sh
|
|
||||||
# RUN chmod 552 /init.sh
|
|
||||||
|
|
||||||
# # ENTRYPOINT [ "/init.sh" ]
|
# Python-Anwendungscode ins Image kopieren (inkl. templates/index.html)
|
||||||
# ENTRYPOINT [ "sh", "/init.sh" ]
|
COPY App_Server/root/ /usr/opt/pythonapp/App_Server/root/
|
||||||
# CMD []
|
|
||||||
|
|
||||||
|
# Prod-Start-Script
|
||||||
|
COPY App_Server/scripts/init.sh /usr/opt/pythonapp/App_Server/scripts/init.sh
|
||||||
|
RUN chmod +x /usr/opt/pythonapp/App_Server/scripts/init.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["sh", "/usr/opt/pythonapp/App_Server/scripts/init.sh"]
|
||||||
|
|
||||||
|
# ── Stage: dev ───────────────────────────────────────────────────
|
||||||
FROM prod AS dev
|
FROM prod AS dev
|
||||||
ARG NODE_VERSION
|
# Node.js-Version fest im Dockerfile verankert.
|
||||||
ARG NPM_VERSION
|
|
||||||
|
|
||||||
# --- 2. Systemabhängigkeiten (für Python + Node.js) ---
|
# --- 2. Systemabhängigkeiten (für Python + Node.js) ---
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
@@ -41,19 +45,14 @@ RUN apt-get update && \
|
|||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# --- 3. Node.js + npm installieren ---
|
# --- 3. Node.js + npm installieren ---
|
||||||
|
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \
|
|
||||||
apt-get install -y nodejs && \
|
apt-get install -y nodejs && \
|
||||||
npm install -g npm@${NPM_VERSION}
|
npm install -g npm@latest
|
||||||
|
|
||||||
# --- 8. Arbeitsverzeichnis für TypeScript ---
|
# --- 4. Dev-Start-Script kopieren (fuer Konsistenz, wird sonst per bind-mount bereitgestellt) ---
|
||||||
# In dem Entwicklungsverzeichnis (PYTHON_DEV_DIR) existiert dies schon als Unterverzeichnis "Client", daher wird es hier nicht erstellt
|
COPY App_Server/scripts/inittypescriptdev.sh /usr/opt/pythonapp/App_Server/scripts/inittypescriptdev.sh
|
||||||
|
RUN chmod +x /usr/opt/pythonapp/App_Server/scripts/inittypescriptdev.sh
|
||||||
|
|
||||||
# --- 9. TypeScript + Rollup installieren ---
|
|
||||||
# Das Script inittypescriptdev.sh wird in der Entwicklungsumgebung ausgeführt, um die TypeScript-Umgebung zu initialisieren.
|
|
||||||
# Daher ist es nicht notwendig, es hier zu kopieren und auszuführen.
|
|
||||||
# COPY ./scripts/inittypescriptdev.sh /usr/opt/pythonapp/App_Server/scripts/inittypescriptdev.sh
|
|
||||||
# RUN chmod +x /usr/opt/pythonapp/App_Server/scripts/inittypescriptdev.sh
|
|
||||||
ENTRYPOINT ["sh", "/usr/opt/pythonapp/App_Server/scripts/inittypescriptdev.sh"]
|
ENTRYPOINT ["sh", "/usr/opt/pythonapp/App_Server/scripts/inittypescriptdev.sh"]
|
||||||
CMD ["/usr/opt/pythonapp/env/bin/python", "root/runserver.py", "-D"]
|
CMD ["/usr/opt/pythonapp/env/bin/python", "/usr/opt/pythonapp/App_Server/root/runserver.py", "-D"]
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@ from settings import Configuration
|
|||||||
from db import dbauth
|
from db import dbauth
|
||||||
from db import dbapp
|
from db import dbapp
|
||||||
from auth.model.checkdb import checkupdates as checkupdatesauth
|
from auth.model.checkdb import checkupdates as checkupdatesauth
|
||||||
from os import path
|
import os
|
||||||
|
|
||||||
login_manager = LoginManager()
|
login_manager = LoginManager()
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ login_manager = LoginManager()
|
|||||||
def init_app():
|
def init_app():
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
config: Configuration = Configuration("root/config.ini")
|
config: Configuration = Configuration("/usr/opt/pythonapp/App_Server/root/config.ini")
|
||||||
_projektname = config.app_projectname
|
_projektname = config.app_projectname
|
||||||
|
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////usr/var/pythonappdb/{}.db".format(_projektname)
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////usr/var/pythonappdb/{}.db".format(_projektname)
|
||||||
@@ -20,7 +20,7 @@ def init_app():
|
|||||||
"auth": "sqlite:////usr/var/pythonappdb/auth.db",
|
"auth": "sqlite:////usr/var/pythonappdb/auth.db",
|
||||||
"appdb": "sqlite:////usr/var/pythonappdb/{}.db".format(_projektname)
|
"appdb": "sqlite:////usr/var/pythonappdb/{}.db".format(_projektname)
|
||||||
}
|
}
|
||||||
app.config["DEBUG"] = path.exists("root/debug")
|
app.config["DEBUG"] = os.environ.get("APP_DEBUG", "false").lower() in ("true", "1", "yes")
|
||||||
app.config["PROJEKTNAME"] = config.app_projectname
|
app.config["PROJEKTNAME"] = config.app_projectname
|
||||||
app.config["APPID"] = config.app_appid
|
app.config["APPID"] = config.app_appid
|
||||||
app.config["APPVERSION"] = config.clientapp_version
|
app.config["APPVERSION"] = config.clientapp_version
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ def run_server():
|
|||||||
if app.config["DEBUG"] is False:
|
if app.config["DEBUG"] is False:
|
||||||
_server = "waitress"
|
_server = "waitress"
|
||||||
# serve(app, listen='nginx-proxy:8080') # Funktioniert aus unbekannten Gründen nicht. Der Hostname wird im Docker Container nicht korrekt aufgelöst
|
# serve(app, listen='nginx-proxy:8080') # Funktioniert aus unbekannten Gründen nicht. Der Hostname wird im Docker Container nicht korrekt aufgelöst
|
||||||
|
print(f"Server startet mit Server type: {_server}", flush=True)
|
||||||
serve(app, listen='*:8080')
|
serve(app, listen='*:8080')
|
||||||
else:
|
else:
|
||||||
_server = "werkzeug"
|
_server = "werkzeug"
|
||||||
|
print(f"Server startet mit Server type: {_server}", flush=True)
|
||||||
serving.run_simple("0.0.0.0", 8080, app, use_reloader=True)
|
serving.run_simple("0.0.0.0", 8080, app, use_reloader=True)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print(str(ex))
|
print(str(ex))
|
||||||
|
print(f"Server gestartet. Server type: {_server}", flush=True)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = init_app()
|
app = init_app()
|
||||||
|
|||||||
@@ -1,16 +1,7 @@
|
|||||||
# Python virtual Environment anlegen
|
#!/bin/bash
|
||||||
cd /usr/opt/pythonapp
|
# Startet den Python-Server im Prod-Modus.
|
||||||
# Wenn es die Datei pyvenv.cfg im Unterverzeichnis env nocht nicht gibt, muss das
|
# pip install ist nicht mehr noetig — Abhaengigkeiten sind im Image.
|
||||||
# virtuelle Environment angelegt werden
|
# Kein cd noetig — alle Pfade sind absolut.
|
||||||
# if [ ! -s env/pyvenv.cfg ]
|
# Python-Imports funktionieren ueber sys.path[0] (Verzeichnis des Scripts).
|
||||||
# then
|
|
||||||
# echo "Creating Python Virtual environment..."
|
|
||||||
# python -m venv --upgrade-deps /usr/opt/pythonapp/env
|
|
||||||
# echo "Python Virtual environment created."
|
|
||||||
# fi
|
|
||||||
echo "Installing Python requirements..."
|
|
||||||
env/bin/pip install -r root/requirements.txt
|
|
||||||
echo "Python requirements installed."
|
|
||||||
|
|
||||||
echo "Starting Python-Server..."
|
echo "Starting Python-Server..."
|
||||||
env/bin/python root/runserver.py
|
exec /usr/opt/pythonapp/env/bin/python /usr/opt/pythonapp/App_Server/root/runserver.py
|
||||||
@@ -38,5 +38,5 @@ export function getIniValue(value){
|
|||||||
return result["APP"][value]
|
return result["APP"][value]
|
||||||
}
|
}
|
||||||
|
|
||||||
var inifile = readFileSync("../App_Server/root/config.ini").toString()
|
var inifile = readFileSync("/usr/opt/pythonapp/App_Server/root/config.ini").toString()
|
||||||
result = parseINIString(inifile)
|
result = parseINIString(inifile)
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc && rollup -c rollup.config.mjs"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mithril": "^2.2.2"
|
"mithril": "^2.2.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,432 @@
|
|||||||
|
# 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 Python-Code in das App-Image kopiert. Der TypeScript-Quellcode
|
||||||
|
wird waehrend des Docker-Builds in einer Multi-Stage-Build-Stage kompiliert
|
||||||
|
(tsc + rollup); in das finale NGINX-Image wird nur das fertige JS-Bundle
|
||||||
|
uebernommen, nicht der TypeScript-Quellcode. 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).
|
||||||
|
# WICHTIG: Auch bei NGINX_USE_SSL=false duerfen NGINX_CERTS, NGINX_CERT und
|
||||||
|
# NGINX_CERT_KEY NICHT geloescht werden. docker-compose.base.yaml bindet
|
||||||
|
# ${NGINX_CERTS} immer als Volume (/etc/certs) ein — ein fehlender Wert
|
||||||
|
# fuehrt zu einem Compose-Fehler. Bei SSL=false reicht es, Platzhalterwerte
|
||||||
|
# zu setzen (z.B. NGINX_CERTS auf ein beliebiges Verzeichnis zeigen lassen).
|
||||||
|
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
|
||||||
|
# Auch hier gilt: Bei NGINX_USE_SSL=false die Zertifikats-Variablen nicht
|
||||||
|
# loeschen, sondern Platzhalterwerte stehen lassen (s. Hinweis oben).
|
||||||
|
|
||||||
|
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). Auch bei SSL=false erforderlich — Compose bindet diesen Pfad immer als Volume ein |
|
||||||
|
| `NGINX_CERT` | ja | Zertifikatsdatei. Bei SSL=false nicht verwendet, darf aber nicht geloescht werden (Platzhalter reicht) |
|
||||||
|
| `NGINX_CERT_KEY` | ja | Privater Schluessel. Bei SSL=false nicht verwendet, darf aber nicht geloescht werden (Platzhalter reicht) |
|
||||||
|
| `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 (s. `BUILD_ENVIRONMENT`)|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 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`
|
||||||
+26
-4
@@ -1,6 +1,28 @@
|
|||||||
ARG NGINX_VERSION
|
# ── Stage: frontend — baut das TypeScript-JS-Bundle ──────────────
|
||||||
FROM nginx:${NGINX_VERSION}
|
# Node.js, npm und node_modules landen NICHT im Prod-Image.
|
||||||
|
FROM node:lts-bookworm-slim AS frontend
|
||||||
|
# Zielverzeichnis fuer rollup-Output erstellen (absoluter Pfad wie in rollup.config.mjs)
|
||||||
|
RUN mkdir -p /usr/opt/pythonapp/NGINX_Server/html/static
|
||||||
|
WORKDIR /usr/opt/pythonapp/Client
|
||||||
|
# Erst package.json + lockfile kopieren (besseres Layer-Caching)
|
||||||
|
COPY Client/package.json Client/package-lock.json* ./
|
||||||
|
RUN npm ci || npm install
|
||||||
|
# Rest des Client-Quellcodes kopieren
|
||||||
|
COPY Client/ ./
|
||||||
|
# config.ini wird fuer rollup benoetigt (inireader.mjs liest Version/Name)
|
||||||
|
COPY App_Server/root/config.ini /usr/opt/pythonapp/App_Server/root/config.ini
|
||||||
|
# tsc + rollup ausfuehren — Output geht nach /usr/opt/pythonapp/NGINX_Server/html/static/
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ── Stage: nginx ────────────────────────────────────────────────
|
||||||
|
FROM nginx:mainline-alpine
|
||||||
RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
||||||
RUN mkdir -p /etc/certs /etc/nginx/templates
|
RUN mkdir -p /etc/certs /etc/nginx/templates
|
||||||
COPY 10-select-ssl.sh /docker-entrypoint.d/10-select-ssl.sh
|
COPY NGINX_Server/10-select-ssl.sh /docker-entrypoint.d/10-select-ssl.sh
|
||||||
RUN chmod +x /docker-entrypoint.d/10-select-ssl.sh
|
RUN chmod +x /docker-entrypoint.d/10-select-ssl.sh
|
||||||
|
# NGINX Config-Templates ins Image kopieren (in Prod; Dev ueberschreibt per bind-mount)
|
||||||
|
COPY NGINX_Server/configtemplates/ /etc/nginx/configtemplates/
|
||||||
|
# Alle statischen Dateien aus dem Repo kopieren (CSS, favicon, fonts, logo)
|
||||||
|
COPY NGINX_Server/html/static/ /usr/share/nginx/html/static/
|
||||||
|
# JS-Bundle aus der frontend-Stage ueberschreibt ggf. vorhandene alte JS-Dateien
|
||||||
|
COPY --from=frontend /usr/opt/pythonapp/NGINX_Server/html/static/ /usr/share/nginx/html/static/
|
||||||
@@ -2,15 +2,14 @@ name: kbpbase
|
|||||||
services:
|
services:
|
||||||
nginx-proxy:
|
nginx-proxy:
|
||||||
build:
|
build:
|
||||||
context: NGINX_Server
|
context: . # Repo-Root (fuer frontend-Stage im NGINX-Dockerfile)
|
||||||
args: # Übergibt die ARGS an das dockerfile
|
dockerfile: NGINX_Server/Dockerfile # explizit, da Context nicht mehr NGINX_Server/
|
||||||
NGINX_VERSION: ${NGINX_VERSION}
|
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- ${NGINX_HOST_PORT}:4430
|
- ${NGINX_HOST_PORT}:4430
|
||||||
volumes:
|
volumes:
|
||||||
- ${NGINX_STATIC_DIR}:/usr/share/nginx/html:ro
|
# NGINX_STATIC_DIR entfaellt in Prod — statische Dateien sind im NGINX-Image
|
||||||
- ${NGINX_CONFIG_TEMPLATE_DIR}:/etc/nginx/configtemplates:ro
|
# NGINX_CONFIG_TEMPLATE_DIR entfaellt in Prod — Templates sind im Image
|
||||||
|
# Beide werden in Dev per bind-mount ueberschrieben (siehe docker-compose.dev.yaml)
|
||||||
- ${NGINX_CERTS}:/etc/certs
|
- ${NGINX_CERTS}:/etc/certs
|
||||||
environment:
|
environment:
|
||||||
- NGINX_USE_SSL=${NGINX_USE_SSL:-true}
|
- NGINX_USE_SSL=${NGINX_USE_SSL:-true}
|
||||||
@@ -19,15 +18,9 @@ services:
|
|||||||
- NGINX_SERVER_NAME=${NGINX_SERVER_NAME}
|
- NGINX_SERVER_NAME=${NGINX_SERVER_NAME}
|
||||||
pythonapp:
|
pythonapp:
|
||||||
build:
|
build:
|
||||||
context: App_Server
|
context: . # Repo-Root (fuer COPY-Pfade im Dockerfile)
|
||||||
# target: kommt aus dem prod oder dev dockerfile
|
dockerfile: App_Server/Dockerfile # explizit, da Context nicht mehr App_Server/
|
||||||
args: # Übergibt die ARGS an das dockerfile
|
|
||||||
PYTHON_VERSION: ${PYTHON_VERSION}
|
|
||||||
volumes:
|
volumes:
|
||||||
#- ${PYTHON_APP_DIR}:/usr/opt/pythonapp/root
|
|
||||||
- ${PYTHON_DB_DIR}:/usr/var/pythonappdb
|
- ${PYTHON_DB_DIR}:/usr/var/pythonappdb
|
||||||
- python-venv:/usr/opt/pythonapp/env
|
# python-venv Volume entfaellt — venv ist im Image
|
||||||
# - ${PYTHON_ENV_DIR}:/usr/opt/pythonapp/env
|
# (dev-Stage definiert eigenen Volume in docker-compose.dev.yaml)
|
||||||
|
|
||||||
volumes:
|
|
||||||
python-venv:
|
|
||||||
+15
-5
@@ -6,17 +6,27 @@ services:
|
|||||||
service: pythonapp
|
service: pythonapp
|
||||||
build:
|
build:
|
||||||
target: dev
|
target: dev
|
||||||
args: # Übergibt die ARGS an das dockerfile
|
|
||||||
# PYTHON_VERSION: ${PYTHON_VERSION}
|
|
||||||
NODE_VERSION: ${NODE_VERSION:-18}
|
|
||||||
NPM_VERSION: ${NPM_VERSION:-8}
|
|
||||||
environment:
|
environment:
|
||||||
# Globales Vibe-Home innerhalb des Workspace-Bind-Mounts, damit es auf dem Host persistiert
|
# Globales Vibe-Home innerhalb des Workspace-Bind-Mounts, damit es auf dem Host persistiert
|
||||||
- VIBE_HOME=/usr/opt/pythonapp/.vibe-global
|
- VIBE_HOME=/usr/opt/pythonapp/.vibe-global
|
||||||
|
# Debug-Modus aktivieren — Werkzeug-Reloader statt Waitress
|
||||||
|
- APP_DEBUG=true
|
||||||
volumes:
|
volumes:
|
||||||
- ${PYTHON_DEV_DIR}:/usr/opt/pythonapp
|
- ${PYTHON_DEV_DIR}:/usr/opt/pythonapp
|
||||||
# - ${TYPESCRIPT_SRC_DIR}:/usr/opt/typescript
|
# python-venv-dev: venv als Volume, da der bind-mount das Image-venv ueberlagert
|
||||||
|
- python-venv-dev:/usr/opt/pythonapp/env
|
||||||
- node-modules:/usr/opt/typescript/node_modules
|
- node-modules:/usr/opt/typescript/node_modules
|
||||||
|
|
||||||
|
nginx-proxy:
|
||||||
|
extends:
|
||||||
|
file: docker-compose.base.yaml
|
||||||
|
service: nginx-proxy
|
||||||
|
volumes:
|
||||||
|
# Statische Dateien per bind-mount — Aenderungen (tsc/rollup, CSS) sofort sichtbar
|
||||||
|
- ${NGINX_STATIC_DIR}:/usr/share/nginx/html:ro
|
||||||
|
# Config-Templates per bind-mount — Aenderungen an NGINX-Config sofort sichtbar
|
||||||
|
- ${NGINX_CONFIG_TEMPLATE_DIR}:/etc/nginx/configtemplates:ro
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
python-venv-dev:
|
||||||
node-modules:
|
node-modules:
|
||||||
@@ -6,5 +6,9 @@ services:
|
|||||||
service: pythonapp
|
service: pythonapp
|
||||||
build:
|
build:
|
||||||
target: prod
|
target: prod
|
||||||
volumes:
|
# Kein Code-bind-mount mehr — Code ist im Image
|
||||||
- ${PYTHON_APP_DIR}:/usr/opt/pythonapp
|
nginx-proxy:
|
||||||
|
extends:
|
||||||
|
file: docker-compose.base.yaml
|
||||||
|
service: nginx-proxy
|
||||||
|
# Kein STATIC_DIR bind-mount mehr — statische Dateien sind im NGINX-Image
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
services:
|
|
||||||
nginx-proxy:
|
|
||||||
build:
|
|
||||||
context: NGINX_Server
|
|
||||||
args: # Übergibt die ARGS an das dockerfile
|
|
||||||
NGINX_VERSION: ${NGINX_VERSION}
|
|
||||||
|
|
||||||
ports:
|
|
||||||
- ${NGINX_HOST_PORT}:4430
|
|
||||||
volumes:
|
|
||||||
- ${NGINX_STATIC_DIR}:/usr/share/nginx/html:ro
|
|
||||||
- ${NGINX_CONFIG_TEMPLATE_DIR}:/etc/nginx/configtemplates:ro
|
|
||||||
- ${NGINX_CERTS}:/etc/certs
|
|
||||||
environment:
|
|
||||||
- NGINX_USE_SSL=${NGINX_USE_SSL:-true}
|
|
||||||
- NGINX_CERT=${NGINX_CERT}
|
|
||||||
- NGINX_CERT_KEY=${NGINX_CERT_KEY}
|
|
||||||
- NGINX_SERVER_NAME=${NGINX_SERVER_NAME}
|
|
||||||
pythonapp:
|
|
||||||
build:
|
|
||||||
context: App_Server
|
|
||||||
args: # Übergibt die ARGS an das dockerfile
|
|
||||||
PYTHON_VERSION: ${PYTHON_VERSION}
|
|
||||||
volumes:
|
|
||||||
- ${PYTHON_APP_DIR}:/usr/opt/pythonapp/root
|
|
||||||
- ${PYTHON_DB_DIR}:/usr/var/pythonappdb
|
|
||||||
# - ${PYTHON_ENV_DIR}:/usr/opt/pythonapp/env
|
|
||||||
+24
-14
@@ -1,34 +1,44 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# BUILD-UMGEBUNG (zentrale Einstellung — hier dev/prod umschalten)
|
||||||
|
# =============================================================================
|
||||||
|
# Bestimmt, welche docker-compose-*.yaml neben der base-Datei geladen wird.
|
||||||
|
# COMPOSE_FILE wird von Docker Compose automatisch ausgewertet (auch via .env);
|
||||||
|
# mehrere Dateien werden durch ':' getrennt und nacheinander gemerged.
|
||||||
|
BUILD_ENVIRONMENT=dev
|
||||||
|
COMPOSE_FILE=docker-compose.base.yaml:docker-compose.${BUILD_ENVIRONMENT}.yaml
|
||||||
|
|
||||||
# Parameter für NGINX-Server
|
# Parameter für NGINX-Server
|
||||||
NGINX_VERSION=mainline-alpine
|
|
||||||
# SSL für NGINX aktivieren (true) oder deaktivieren (false).
|
# SSL für NGINX aktivieren (true) oder deaktivieren (false).
|
||||||
# Bei false muss NGINX_HOST_PORT angepasst werden (z.B. 8080 statt 443).
|
# Bei false muss NGINX_HOST_PORT angepasst werden (z.B. 8080 statt 443).
|
||||||
|
#
|
||||||
|
# WICHTIG: Auch wenn SSL deaktiviert wird (NGINX_USE_SSL=false), duerfen die
|
||||||
|
# Zertifikats-Variablen (NGINX_CERTS, NGINX_CERT, NGINX_CERT_KEY) NICHT geloescht
|
||||||
|
# werden. docker-compose.base.yaml bindet ${NGINX_CERTS} immer als Volume
|
||||||
|
# (/etc/certs) ein — ein fehlender Wert fuehrt zu einem Compose-Fehler.
|
||||||
|
# NGINX_CERT und NGINX_CERT_KEY werden ebenfalls immer als Umgebungsvariablen
|
||||||
|
# an den Container uebergeben; bei SSL=false werden sie nicht verwendet, muessen
|
||||||
|
# aber als Platzhalter erhalten bleiben. Es reicht, gueltige Platzhalterwerte
|
||||||
|
# einzutragen (z.B. NGINX_CERTS auf ein beliebiges Verzeichnis zeigen lassen).
|
||||||
NGINX_USE_SSL=true
|
NGINX_USE_SSL=true
|
||||||
NGINX_HOST_PORT=443
|
NGINX_HOST_PORT=443
|
||||||
NGINX_SERVER_NAME=kbp_crm.mylocal.de
|
NGINX_SERVER_NAME=kbp_crm.mylocal.de
|
||||||
|
# NGINX_STATIC_DIR: nur in Dev benoetigt (bind-mount fuer statische Dateien).
|
||||||
|
# In Prod liegen die statischen Dateien im NGINX-Image.
|
||||||
NGINX_STATIC_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/html
|
NGINX_STATIC_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/html
|
||||||
|
# NGINX_CONFIG_TEMPLATE_DIR: nur in Dev benoetigt (bind-mount fuer NGINX-Templates).
|
||||||
|
# In Prod liegen die Templates im NGINX-Image.
|
||||||
NGINX_CONFIG_TEMPLATE_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/configtemplates
|
NGINX_CONFIG_TEMPLATE_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/configtemplates
|
||||||
NGINX_CERTS=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/certs
|
NGINX_CERTS=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/certs
|
||||||
NGINX_CERT=wildcard.mylocal.crt
|
NGINX_CERT=wildcard.mylocal.crt
|
||||||
NGINX_CERT_KEY=wildcard.mylocal.key
|
NGINX_CERT_KEY=wildcard.mylocal.key
|
||||||
|
|
||||||
# Parameter for Python App-Server
|
# Parameter for Python App-Server
|
||||||
PYTHON_VERSION=slim-bookworm
|
# PYTHON_APP_DIR entfaellt — Code wird in Prod ins Image gebaut (Option B).
|
||||||
PYTHON_APP_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/root
|
# In Dev wird PYTHON_DEV_DIR als bind-mount verwendet (siehe docker-compose.dev.yaml).
|
||||||
PYTHON_DEV_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm
|
PYTHON_DEV_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm
|
||||||
PYTHON_DB_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/data
|
PYTHON_DB_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/data
|
||||||
# PYTHON_ENV_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/env
|
# PYTHON_ENV_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/env
|
||||||
|
|
||||||
# Parameter für Dev-Mode (Development-Container für VS-Code)
|
|
||||||
NODE_VERSION=lts
|
|
||||||
NPM_VERSION=latest
|
|
||||||
|
|
||||||
# Umgebung für Docker-Compose-Stack (prod oder dev).
|
|
||||||
# Bestimmt, welche docker-compose-*.yaml neben der base-Datei geladen wird.
|
|
||||||
# COMPOSE_FILE wird von Docker Compose automatisch ausgewertet (auch via .env);
|
|
||||||
# mehrere Dateien werden durch ':' getrennt und nacheinander gemerged.
|
|
||||||
# Dadurch entfällt der mehrfache Aufruf des -f Parameters beim docker compose Aufruf.
|
|
||||||
BUILD_ENVIRONMENT=dev
|
|
||||||
COMPOSE_FILE=docker-compose.base.yaml:docker-compose.${BUILD_ENVIRONMENT}.yaml
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# ZITADEL OIDC SETTINGS
|
# ZITADEL OIDC SETTINGS
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Deploy-Script: Promotion nach PROD (manuelles OK erforderlich)
|
||||||
|
# Wird manuell aufgerufen, nachdem test-prod verifiziert wurde.
|
||||||
|
# Voraussetzungen auf dem Server: git, docker, docker compose.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Konfiguration — an die jeweilige Server-Umgebung anpassen
|
||||||
|
REPO_DIR=/opt/kbcrm-prod/repo
|
||||||
|
COMPOSE_FILE=docker-compose.prod.yaml
|
||||||
|
ENV_FILE=/opt/kbcrm-prod/.env
|
||||||
|
PROD_PORT=443
|
||||||
|
|
||||||
|
echo "=== Deploy KB-CRM PROD ==="
|
||||||
|
|
||||||
|
# Sicherheitsabfrage — nur bei manueller Eingabe von "yes" wird fortgesetzt
|
||||||
|
echo "This will deploy to PRODUCTION. Continue? (yes/no)"
|
||||||
|
read -r confirmation
|
||||||
|
if [ "$confirmation" != "yes" ]; then
|
||||||
|
echo "Aborted."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Code aktualisieren
|
||||||
|
cd "$REPO_DIR"
|
||||||
|
echo "=== Pulling latest code ==="
|
||||||
|
git fetch origin main
|
||||||
|
git checkout main
|
||||||
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
# 2. Images neu bauen und Container starten
|
||||||
|
echo "=== Building and starting containers ==="
|
||||||
|
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up -d --build
|
||||||
|
|
||||||
|
# 3. Health-Check
|
||||||
|
echo "=== Waiting for container startup ==="
|
||||||
|
sleep 10
|
||||||
|
if curl -sf "http://localhost:${PROD_PORT}/health-check" >/dev/null 2>&1; then
|
||||||
|
echo "Health check: OK"
|
||||||
|
else
|
||||||
|
echo "WARNING: Health check failed — check container logs with:"
|
||||||
|
echo " docker compose --env-file $ENV_FILE -f $COMPOSE_FILE logs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Deploy PROD complete ==="
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Deploy-Script: Automatisches Deployment nach TEST (test-prod)
|
||||||
|
# Wird durch Git-Hook/Webhook oder manuell aufgerufen.
|
||||||
|
# Voraussetzungen auf dem Server: git, docker, docker compose.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Konfiguration — an die jeweilige Server-Umgebung anpassen
|
||||||
|
REPO_DIR=/opt/kbcrm-test/repo
|
||||||
|
COMPOSE_FILE=docker-compose.prod.yaml
|
||||||
|
ENV_FILE=/opt/kbcrm-test/.env
|
||||||
|
TEST_PORT=8443
|
||||||
|
|
||||||
|
echo "=== Deploy KB-CRM TEST ==="
|
||||||
|
|
||||||
|
# 1. Code aktualisieren
|
||||||
|
cd "$REPO_DIR"
|
||||||
|
echo "=== Pulling latest code ==="
|
||||||
|
git fetch origin main
|
||||||
|
git checkout main
|
||||||
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
# 2. Images neu bauen und Container starten
|
||||||
|
echo "=== Building and starting containers ==="
|
||||||
|
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up -d --build
|
||||||
|
|
||||||
|
# 3. Health-Check
|
||||||
|
echo "=== Waiting for container startup ==="
|
||||||
|
sleep 10
|
||||||
|
if curl -sf "http://localhost:${TEST_PORT}/health-check" >/dev/null 2>&1; then
|
||||||
|
echo "Health check: OK"
|
||||||
|
else
|
||||||
|
echo "WARNING: Health check failed — check container logs with:"
|
||||||
|
echo " docker compose --env-file $ENV_FILE -f $COMPOSE_FILE logs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Deploy TEST complete ==="
|
||||||
Reference in new issue
Block a user