From 3b3e2893e54efff273c2ebe21d2985cc0786f400 Mon Sep 17 00:00:00 2001 From: Gerd Date: Sun, 13 Sep 2026 18:40:55 +0200 Subject: [PATCH] feat(deploy): Multi-Stage-Docker-Build fuer automatisches Deployment - App_Server/Dockerfile: Build-Context auf Repo-Root, COPY-Pfade angepasst, ENTRYPOINT aktiviert, dev-Stage mit inittypescriptdev.sh - NGINX_Server/Dockerfile: Multi-Stage mit frontend-Stage (Node.js baut TypeScript), statische Dateien und Config-Templates ins Image kopiert - docker-compose.base.yaml: Context auf '.', python-venv Volume entfernt, NGINX_STATIC_DIR/CONFIG_TEMPLATE_DIR bind-mounts in Dev verschoben - docker-compose.dev.yaml: python-venv-dev Volume, APP_DEBUG=true, nginx-proxy mit bind-mounts fuer statische Dateien und Templates - docker-compose.prod.yaml: Code-bind-mount entfernt, nginx-proxy extends - approot.py: absolute Pfade, Debug-Modus via APP_DEBUG Umgebungsvariable - init.sh: vereinfacht (kein cd/pip, absolute Pfade) - inireader.mjs: absoluter Pfad fuer config.ini - package.json: scripts.build (tsc + rollup) ergaenzt - .dockerignore, deploy-kbcrm-test.sh, deploy-kbcrm-prod.sh erstellt - docker-compose.save.yaml geloescht - env-sample: BUILD_ENVIRONMENT nach oben, Dev-only Variablen markiert Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- .dockerignore | 8 +++++++ App_Server/Dockerfile | 33 +++++++++++++++------------ App_Server/root/approot.py | 6 ++--- App_Server/scripts/init.sh | 21 +++++------------ Client/inireader.mjs | 2 +- Client/package.json | 3 +++ NGINX_Server/Dockerfile | 30 ++++++++++++++++++++++-- docker-compose.base.yaml | 30 ++++++++++++------------ docker-compose.dev.yaml | 19 +++++++++++++--- docker-compose.prod.yaml | 8 +++++-- docker-compose.save.yaml | 27 ---------------------- env-sample | 24 ++++++++++++-------- scripts/deploy-kbcrm-prod.sh | 44 ++++++++++++++++++++++++++++++++++++ scripts/deploy-kbcrm-test.sh | 36 +++++++++++++++++++++++++++++ 14 files changed, 200 insertions(+), 91 deletions(-) create mode 100644 .dockerignore delete mode 100644 docker-compose.save.yaml create mode 100644 scripts/deploy-kbcrm-prod.sh create mode 100644 scripts/deploy-kbcrm-test.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..296bb1a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.git/ +Client/node_modules/ +Client/tsout/ +App_Server/data/ +App_Server/env/ +oidc-test/ +*.pyc +__pycache__/ diff --git a/App_Server/Dockerfile b/App_Server/Dockerfile index e1d0023..bbd86c8 100644 --- a/App_Server/Dockerfile +++ b/App_Server/Dockerfile @@ -1,6 +1,10 @@ ARG PYTHON_VERSION ARG NODE_VERSION ARG NPM_VERSION + +# ── Stage: prod ────────────────────────────────────────────────── +# Build-Context ist das Repo-Root (.), daher muessen alle COPY-Pfade +# mit App_Server/ praefigiert werden. FROM python:${PYTHON_VERSION} AS prod RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime RUN apt-get clean && apt-get update && apt-get install -y locales @@ -12,15 +16,19 @@ RUN locale-gen RUN mkdir -p /usr/opt/pythonapp/App_Server/root /usr/opt/pythonapp/env /usr/var/pythonappdata WORKDIR /usr/opt/pythonapp 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 -# COPY scripts/init.sh /init.sh -# RUN chmod 552 /init.sh -# # ENTRYPOINT [ "/init.sh" ] -# ENTRYPOINT [ "sh", "/init.sh" ] -# CMD [] +# Python-Anwendungscode ins Image kopieren (inkl. templates/index.html) +COPY App_Server/root/ /usr/opt/pythonapp/App_Server/root/ +# 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 ARG NODE_VERSION ARG NPM_VERSION @@ -41,19 +49,14 @@ RUN apt-get update && \ && rm -rf /var/lib/apt/lists/* # --- 3. Node.js + npm installieren --- - RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - && \ apt-get install -y nodejs && \ npm install -g npm@${NPM_VERSION} -# --- 8. Arbeitsverzeichnis für TypeScript --- -# In dem Entwicklungsverzeichnis (PYTHON_DEV_DIR) existiert dies schon als Unterverzeichnis "Client", daher wird es hier nicht erstellt +# --- 4. Dev-Start-Script kopieren (fuer Konsistenz, wird sonst per bind-mount bereitgestellt) --- +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"] -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"] diff --git a/App_Server/root/approot.py b/App_Server/root/approot.py index ea2ede9..da9961e 100644 --- a/App_Server/root/approot.py +++ b/App_Server/root/approot.py @@ -4,7 +4,7 @@ from settings import Configuration from db import dbauth from db import dbapp from auth.model.checkdb import checkupdates as checkupdatesauth -from os import path +import os login_manager = LoginManager() @@ -12,7 +12,7 @@ login_manager = LoginManager() def init_app(): app = Flask(__name__) - config: Configuration = Configuration("root/config.ini") + config: Configuration = Configuration("/usr/opt/pythonapp/App_Server/root/config.ini") _projektname = config.app_projectname 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", "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["APPID"] = config.app_appid app.config["APPVERSION"] = config.clientapp_version diff --git a/App_Server/scripts/init.sh b/App_Server/scripts/init.sh index c7583ad..c869720 100644 --- a/App_Server/scripts/init.sh +++ b/App_Server/scripts/init.sh @@ -1,16 +1,7 @@ -# Python virtual Environment anlegen -cd /usr/opt/pythonapp -# Wenn es die Datei pyvenv.cfg im Unterverzeichnis env nocht nicht gibt, muss das -# virtuelle Environment angelegt werden -# if [ ! -s env/pyvenv.cfg ] -# 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." - +#!/bin/bash +# Startet den Python-Server im Prod-Modus. +# pip install ist nicht mehr noetig — Abhaengigkeiten sind im Image. +# Kein cd noetig — alle Pfade sind absolut. +# Python-Imports funktionieren ueber sys.path[0] (Verzeichnis des Scripts). echo "Starting Python-Server..." -env/bin/python root/runserver.py \ No newline at end of file +exec /usr/opt/pythonapp/env/bin/python /usr/opt/pythonapp/App_Server/root/runserver.py \ No newline at end of file diff --git a/Client/inireader.mjs b/Client/inireader.mjs index c8ef556..93bc92e 100644 --- a/Client/inireader.mjs +++ b/Client/inireader.mjs @@ -38,5 +38,5 @@ export function getIniValue(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) diff --git a/Client/package.json b/Client/package.json index ab198a1..eb07143 100644 --- a/Client/package.json +++ b/Client/package.json @@ -1,4 +1,7 @@ { + "scripts": { + "build": "tsc && rollup -c rollup.config.mjs" + }, "dependencies": { "mithril": "^2.2.2" }, diff --git a/NGINX_Server/Dockerfile b/NGINX_Server/Dockerfile index b3add02..14763a7 100644 --- a/NGINX_Server/Dockerfile +++ b/NGINX_Server/Dockerfile @@ -1,6 +1,32 @@ ARG NGINX_VERSION +ARG NODE_VERSION +ARG NPM_VERSION + +# ── Stage: frontend — baut das TypeScript-JS-Bundle ────────────── +# Node.js, npm und node_modules landen NICHT im Prod-Image. +FROM node:${NODE_VERSION}-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:${NGINX_VERSION} RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime RUN mkdir -p /etc/certs /etc/nginx/templates -COPY 10-select-ssl.sh /docker-entrypoint.d/10-select-ssl.sh -RUN chmod +x /docker-entrypoint.d/10-select-ssl.sh \ No newline at end of file +COPY NGINX_Server/10-select-ssl.sh /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/ \ No newline at end of file diff --git a/docker-compose.base.yaml b/docker-compose.base.yaml index 394dd0a..7f97777 100644 --- a/docker-compose.base.yaml +++ b/docker-compose.base.yaml @@ -2,15 +2,19 @@ name: kbpbase services: nginx-proxy: build: - context: NGINX_Server - args: # Übergibt die ARGS an das dockerfile - NGINX_VERSION: ${NGINX_VERSION} + context: . # Repo-Root (fuer frontend-Stage im NGINX-Dockerfile) + dockerfile: NGINX_Server/Dockerfile # explizit, da Context nicht mehr NGINX_Server/ + args: + NGINX_VERSION: ${NGINX_VERSION} + NODE_VERSION: ${NODE_VERSION} + NPM_VERSION: ${NPM_VERSION} ports: - ${NGINX_HOST_PORT}:4430 volumes: - - ${NGINX_STATIC_DIR}:/usr/share/nginx/html:ro - - ${NGINX_CONFIG_TEMPLATE_DIR}:/etc/nginx/configtemplates:ro + # NGINX_STATIC_DIR entfaellt in Prod — statische Dateien sind im NGINX-Image + # 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 environment: - NGINX_USE_SSL=${NGINX_USE_SSL:-true} @@ -19,15 +23,13 @@ services: - NGINX_SERVER_NAME=${NGINX_SERVER_NAME} pythonapp: build: - context: App_Server - # target: kommt aus dem prod oder dev dockerfile - args: # Übergibt die ARGS an das dockerfile + context: . # Repo-Root (fuer COPY-Pfade im Dockerfile) + dockerfile: App_Server/Dockerfile # explizit, da Context nicht mehr App_Server/ + args: PYTHON_VERSION: ${PYTHON_VERSION} + NODE_VERSION: ${NODE_VERSION} # fuer dev-Stage + NPM_VERSION: ${NPM_VERSION} # fuer dev-Stage volumes: - #- ${PYTHON_APP_DIR}:/usr/opt/pythonapp/root - ${PYTHON_DB_DIR}:/usr/var/pythonappdb - - python-venv:/usr/opt/pythonapp/env - # - ${PYTHON_ENV_DIR}:/usr/opt/pythonapp/env - -volumes: - python-venv: \ No newline at end of file + # python-venv Volume entfaellt — venv ist im Image + # (dev-Stage definiert eigenen Volume in docker-compose.dev.yaml) \ No newline at end of file diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index 900e866..859f58f 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -6,17 +6,30 @@ services: service: pythonapp build: target: dev - args: # Übergibt die ARGS an das dockerfile - # PYTHON_VERSION: ${PYTHON_VERSION} + args: NODE_VERSION: ${NODE_VERSION:-18} NPM_VERSION: ${NPM_VERSION:-8} environment: # Globales Vibe-Home innerhalb des Workspace-Bind-Mounts, damit es auf dem Host persistiert - VIBE_HOME=/usr/opt/pythonapp/.vibe-global + # Debug-Modus aktivieren — Werkzeug-Reloader statt Waitress + - APP_DEBUG=true volumes: - ${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 + 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: + python-venv-dev: node-modules: \ No newline at end of file diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml index 381dc04..1d1d80a 100644 --- a/docker-compose.prod.yaml +++ b/docker-compose.prod.yaml @@ -6,5 +6,9 @@ services: service: pythonapp build: target: prod - volumes: - - ${PYTHON_APP_DIR}:/usr/opt/pythonapp \ No newline at end of file + # Kein Code-bind-mount mehr — Code ist im Image + nginx-proxy: + extends: + file: docker-compose.base.yaml + service: nginx-proxy + # Kein STATIC_DIR bind-mount mehr — statische Dateien sind im NGINX-Image \ No newline at end of file diff --git a/docker-compose.save.yaml b/docker-compose.save.yaml deleted file mode 100644 index 0cda9af..0000000 --- a/docker-compose.save.yaml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/env-sample b/env-sample index 7481c5d..06318a8 100644 --- a/env-sample +++ b/env-sample @@ -1,3 +1,12 @@ +# ============================================================================= +# 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 NGINX_VERSION=mainline-alpine # SSL für NGINX aktivieren (true) oder deaktivieren (false). @@ -5,7 +14,11 @@ NGINX_VERSION=mainline-alpine NGINX_USE_SSL=true NGINX_HOST_PORT=443 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_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_CERTS=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/NGINX_Server/certs NGINX_CERT=wildcard.mylocal.crt @@ -13,7 +26,8 @@ NGINX_CERT_KEY=wildcard.mylocal.key # Parameter for Python App-Server PYTHON_VERSION=slim-bookworm -PYTHON_APP_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/root +# PYTHON_APP_DIR entfaellt — Code wird in Prod ins Image gebaut (Option B). +# 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_DB_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/data # PYTHON_ENV_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/env @@ -22,14 +36,6 @@ PYTHON_DB_DIR=/home/schoschi/Entwicklung/Projekte_Runden/kbcrm/App_Server/data 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 # ============================================================================= diff --git a/scripts/deploy-kbcrm-prod.sh b/scripts/deploy-kbcrm-prod.sh new file mode 100644 index 0000000..07b236b --- /dev/null +++ b/scripts/deploy-kbcrm-prod.sh @@ -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 ===" diff --git a/scripts/deploy-kbcrm-test.sh b/scripts/deploy-kbcrm-test.sh new file mode 100644 index 0000000..9a5e148 --- /dev/null +++ b/scripts/deploy-kbcrm-test.sh @@ -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 ==="