Récupère les derniers commits (git pull), reconstruit l'image légère et recrée le conteneur en une seule commande — cycle de mise à jour complet du Pi après un push vers origin. Le cache de tuiles est conservé.
181 lines
6.4 KiB
Bash
Executable File
181 lines
6.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# Stack webapp LiDAR — gestion de la stack compose sur la machine légère
|
|
# (Raspberry Pi). Cf. docs/DEPLOY_WEBAPP.md.
|
|
#
|
|
# Pilote docker compose (jamais docker run direct, qui ignorerait labels et
|
|
# volumes de l'override) :
|
|
# - docker-compose.webapp.yml (image légère Dockerfile.webapp, port 8973) ;
|
|
# - docker-compose.webapp.override.yml s'il existe (non versionné : labels
|
|
# Traefik, volume réel, environnement local) — chargé automatiquement :
|
|
# la route publique HTTPS et le cache de tuiles réels sont préservés.
|
|
#
|
|
# Configuration : variables dans webapp.env (modèle : webapp.env.example,
|
|
# non versionné) ou exportées — elles alimentent l'interpolation compose
|
|
# (${LIDAR_WEBAPP_HOST} des labels Traefik, etc.) ; l'environnement du
|
|
# CONTENEUR vit dans les fichiers compose / override.
|
|
#
|
|
# HTTPS : terminé par Traefik (override). Sans Traefik, monter ./tls via un
|
|
# override local avec LIDAR_SSL_CERTFILE / LIDAR_SSL_KEYFILE (cf.
|
|
# make-tls-cert.sh) — ce script ne gère plus le certificat auto-signé.
|
|
#
|
|
# Usage :
|
|
# ./serve-webapp.sh [start] démarrer (build + arrière-plan, redémarrage auto)
|
|
# ./serve-webapp.sh stop arrêter et supprimer la stack (cache conservé)
|
|
# ./serve-webapp.sh restart reconstruire l'image et recréer le conteneur
|
|
# ./serve-webapp.sh redeploir git pull + rebuild de l'image + redémarrage du conteneur
|
|
# ./serve-webapp.sh status état du conteneur et de la dernière sync
|
|
# ./serve-webapp.sh sync forcer un rebuild + régénération des vignettes
|
|
# ./serve-webapp.sh logs suivre les logs du conteneur
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
CONTAINER="lidar-webapp"
|
|
COMPOSE_BASE="docker-compose.webapp.yml"
|
|
COMPOSE_OVERRIDE="docker-compose.webapp.override.yml"
|
|
|
|
# Configuration locale (non versionnée) : webapp.env surcharge l'environnement
|
|
# (sert à l'interpolation ${...} des fichiers compose).
|
|
if [ -f "${SCRIPT_DIR}/webapp.env" ]; then
|
|
set -a
|
|
# shellcheck disable=SC1091
|
|
. "${SCRIPT_DIR}/webapp.env"
|
|
set +a
|
|
fi
|
|
WEBAPP_PORT="${WEBAPP_PORT:-8973}"
|
|
|
|
COMPOSE_FILES=(-f "${SCRIPT_DIR}/${COMPOSE_BASE}")
|
|
if [ -f "${SCRIPT_DIR}/${COMPOSE_OVERRIDE}" ]; then
|
|
COMPOSE_FILES+=(-f "${SCRIPT_DIR}/${COMPOSE_OVERRIDE}")
|
|
fi
|
|
|
|
compose() {
|
|
docker compose "${COMPOSE_FILES[@]}" "$@"
|
|
}
|
|
|
|
# Port hôte réellement publié par le conteneur (mapping compose) ; repli sur
|
|
# WEBAPP_PORT tant que le conteneur est arrêté.
|
|
published_port() {
|
|
local p
|
|
p="$(docker port "$CONTAINER" 8973/tcp 2>/dev/null | head -1 | sed 's/.*://')"
|
|
echo "${p:-$WEBAPP_PORT}"
|
|
}
|
|
|
|
lan_ip() {
|
|
hostname -I 2> /dev/null | awk '{print $1}'
|
|
}
|
|
|
|
wait_up() {
|
|
echo -n "Attente du serveur sur le port $1..."
|
|
local up=0 i
|
|
for i in $(seq 1 30); do
|
|
if curl -fsS "http://127.0.0.1:$1/api/status" > /dev/null 2>&1; then
|
|
up=1
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
if [ "$up" != "1" ]; then
|
|
echo " KO (voir ./serve-webapp.sh logs)" >&2
|
|
exit 1
|
|
fi
|
|
echo " OK"
|
|
}
|
|
|
|
cmd_start() {
|
|
compose up -d --build
|
|
wait_up "$(published_port)"
|
|
local port
|
|
port="$(published_port)"
|
|
echo "============================================"
|
|
echo " Carte LiDAR — webapp (${CONTAINER})"
|
|
echo "============================================"
|
|
echo " URL : http://127.0.0.1:${port}/"
|
|
if [ -n "$(lan_ip)" ]; then
|
|
echo " URL (LAN) : http://$(lan_ip):${port}/"
|
|
fi
|
|
if [ -f "${SCRIPT_DIR}/${COMPOSE_OVERRIDE}" ]; then
|
|
echo " Override compose : ${COMPOSE_OVERRIDE} chargé (Traefik/volume local)"
|
|
else
|
|
echo " Override compose : absent (HTTP direct, sans Traefik)"
|
|
fi
|
|
echo " Génération distante: ${LIDAR_GENERATION_URL:-non configurée (override / webapp.env)}"
|
|
echo "============================================"
|
|
}
|
|
|
|
cmd_stop() {
|
|
compose down
|
|
echo "Stack webapp arrêtée (conteneur ${CONTAINER} supprimé, cache conservé)."
|
|
}
|
|
|
|
cmd_restart() {
|
|
compose up -d --build --force-recreate
|
|
wait_up "$(published_port)"
|
|
echo "Stack webapp recréée (image reconstruite, relit webapp.env)."
|
|
}
|
|
|
|
# Mise à jour complète du checkout git + rebuild de l'image + redémarrage du
|
|
# conteneur. À lancer sur le Pi après un push vers origin : récupère les
|
|
# derniers commits, reconstruit l'image légère et recrée le conteneur. Le
|
|
# cache de tuiles (output/) est conservé — les vignettes déjà présentes ne
|
|
# sont pas régénérées (voir sync pour forcer un rebuild des vignettes).
|
|
cmd_redeploy() {
|
|
if [ ! -d "${SCRIPT_DIR}/.git" ]; then
|
|
echo "Échec : ${SCRIPT_DIR} n'est pas un dépôt git — impossible de faire git pull." >&2
|
|
exit 1
|
|
fi
|
|
echo "============================================"
|
|
echo " Redéploiement webapp (${CONTAINER})"
|
|
echo "============================================"
|
|
echo " Checkout git : ${SCRIPT_DIR}"
|
|
echo " Récupération des derniers commits (git pull)..."
|
|
git -C "${SCRIPT_DIR}" pull --ff-only
|
|
echo " Image reconstruite, conteneur recréé..."
|
|
compose up -d --build --force-recreate
|
|
wait_up "$(published_port)"
|
|
local port
|
|
port="$(published_port)"
|
|
echo "============================================"
|
|
echo " Webapp redéployée — http://127.0.0.1:${port}/"
|
|
echo "============================================"
|
|
}
|
|
|
|
cmd_status() {
|
|
compose ps
|
|
local port
|
|
port="$(published_port)"
|
|
if curl -fsS "http://127.0.0.1:${port}/api/sync" 2> /dev/null; then
|
|
echo ""
|
|
else
|
|
echo "Webapp : injoignable sur http://127.0.0.1:${port}" >&2
|
|
fi
|
|
}
|
|
|
|
cmd_sync() {
|
|
local port code
|
|
port="$(published_port)"
|
|
code="$(curl -s -o /dev/null -w '%{http_code}' -X POST "http://127.0.0.1:${port}/api/sync" || true)"
|
|
case "$code" in
|
|
200) echo "Sync lancée (suivi : ./serve-webapp.sh status, logs : ./serve-webapp.sh logs)" ;;
|
|
409) echo "Une sync est déjà en cours (suivi : ./serve-webapp.sh status)" ;;
|
|
*)
|
|
echo "Échec : HTTP ${code:-pas de réponse} (webapp injoignable sur http://127.0.0.1:${port} ?)" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
CMD="${1:-start}"
|
|
case "$CMD" in
|
|
start) cmd_start ;;
|
|
stop) cmd_stop ;;
|
|
restart) cmd_restart ;;
|
|
redeploir) cmd_redeploy ;;
|
|
status) cmd_status ;;
|
|
sync) cmd_sync ;;
|
|
logs) compose logs -f webapp ;;
|
|
*)
|
|
echo "Usage : $0 [start|stop|restart|redeploir|status|sync|logs]" >&2
|
|
exit 1
|
|
;;
|
|
esac
|