- scripts/deploy.sh: Code-Sync + Docker-Build + Container-Restart + Health-Check - scripts/deploy-db.sh: DB-Upload + Migrationen (FTS5, Strang, Fristen) - Dockerfile: Multi-stage Build (Node 20 + Python 3.12) - Production deployed + verifiziert (antraege.toppyr.de health OK) Closes #8
114 lines
3.6 KiB
Bash
Executable File
114 lines
3.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Deploy Antragstracker auf VServer
|
|
# Usage: ./scripts/deploy.sh [--build-only] [--full] [--skip-frontend]
|
|
#
|
|
# Modes:
|
|
# (default) Build + deploy code, restart container
|
|
# --build-only Build Docker image on server, don't restart
|
|
# --full Full deploy: frontend build + code sync + docker rebuild + restart
|
|
# --skip-frontend Skip local frontend build (use existing build/)
|
|
#
|
|
# Voraussetzung: ssh vserver funktioniert
|
|
|
|
set -euo pipefail
|
|
|
|
VSERVER="vserver"
|
|
REMOTE_DIR="/opt/antragstracker"
|
|
CONTAINER="antragstracker-hagen"
|
|
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
|
# Parse args
|
|
BUILD_ONLY=false
|
|
SKIP_FRONTEND=false
|
|
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--build-only) BUILD_ONLY=true ;;
|
|
--full) ;; # default behavior
|
|
--skip-frontend) SKIP_FRONTEND=true ;;
|
|
-h|--help)
|
|
echo "Usage: $0 [--build-only] [--full] [--skip-frontend]"
|
|
exit 0 ;;
|
|
*) echo "Unknown arg: $arg"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
cd "$PROJECT_DIR"
|
|
|
|
# 1. Frontend bauen (lokal)
|
|
if [ "$SKIP_FRONTEND" = false ]; then
|
|
echo "🔨 Frontend bauen..."
|
|
cd frontend && npm run build && cd ..
|
|
echo " ✓ Frontend build fertig ($(du -sh frontend/build | cut -f1))"
|
|
else
|
|
echo "⏭️ Frontend-Build übersprungen"
|
|
fi
|
|
|
|
# 2. Code zum VServer synchronisieren
|
|
echo "📦 Code synchronisieren..."
|
|
tar czf /tmp/antragstracker-deploy.tar.gz \
|
|
--exclude='.git' \
|
|
--exclude='.venv' \
|
|
--exclude='venv' \
|
|
--exclude='node_modules' \
|
|
--exclude='frontend/.svelte-kit' \
|
|
--exclude='data' \
|
|
--exclude='*.log' \
|
|
--exclude='*.pyc' \
|
|
--exclude='__pycache__' \
|
|
--exclude='.DS_Store' \
|
|
--exclude='.pytest_cache' \
|
|
--exclude='tracker.db*' \
|
|
--exclude='antraege.db' \
|
|
--exclude='.github' \
|
|
--exclude='logs' \
|
|
-C "$(dirname "$PROJECT_DIR")" "$(basename "$PROJECT_DIR")"
|
|
|
|
scp /tmp/antragstracker-deploy.tar.gz "$VSERVER:/tmp/"
|
|
ssh "$VSERVER" "cd /opt && tar xzf /tmp/antragstracker-deploy.tar.gz && rm /tmp/antragstracker-deploy.tar.gz"
|
|
rm -f /tmp/antragstracker-deploy.tar.gz
|
|
echo " ✓ Code synchronisiert"
|
|
|
|
# 3. Docker Image bauen (auf VServer)
|
|
echo "🐳 Docker Image bauen auf VServer..."
|
|
ssh "$VSERVER" "cd $REMOTE_DIR && docker compose build --no-cache"
|
|
echo " ✓ Image gebaut"
|
|
|
|
if [ "$BUILD_ONLY" = true ]; then
|
|
echo "⏹️ Build-only Mode — Container wird nicht neu gestartet"
|
|
exit 0
|
|
fi
|
|
|
|
# 4. Container neu starten
|
|
echo "🔄 Container neu starten..."
|
|
ssh "$VSERVER" "cd $REMOTE_DIR && docker compose up -d"
|
|
echo " ✓ Container gestartet"
|
|
|
|
# 5. Warten + Health-Check
|
|
echo "⏳ Warte auf Startup (5s)..."
|
|
sleep 5
|
|
|
|
echo "🏥 Health-Check..."
|
|
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://antraege.toppyr.de/api/health" 2>/dev/null || echo "000")
|
|
|
|
if [ "$HTTP_STATUS" = "200" ]; then
|
|
echo " ✓ Health-Check OK (HTTP $HTTP_STATUS)"
|
|
elif [ "$HTTP_STATUS" = "000" ]; then
|
|
sleep 5
|
|
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://antraege.toppyr.de/api/health" 2>/dev/null || echo "000")
|
|
if [ "$HTTP_STATUS" = "200" ]; then
|
|
echo " ✓ Health-Check OK (HTTP $HTTP_STATUS, 2. Versuch)"
|
|
else
|
|
echo " ⚠️ Health-Check fehlgeschlagen (HTTP $HTTP_STATUS)"
|
|
echo " Logs prüfen: ssh $VSERVER 'docker logs --tail 20 $CONTAINER'"
|
|
fi
|
|
else
|
|
echo " ⚠️ Health-Check: HTTP $HTTP_STATUS"
|
|
echo " Logs prüfen: ssh $VSERVER 'docker logs --tail 20 $CONTAINER'"
|
|
fi
|
|
|
|
echo ""
|
|
echo "✅ Deploy fertig!"
|
|
echo " URL: https://antraege.toppyr.de"
|
|
echo " Logs: ssh $VSERVER 'docker logs --tail 50 $CONTAINER'"
|