Fix upgrade script for Gancio config loss and LSIO volume shadowing
Two issues occurred during upgrades: 1. Gancio config.json lost when Docker volume name prefix changes (e.g., changemakerlite_ vs changemaker-lite_). Gancio finds existing DB but no config and enters restart loop. Fix: verify_gancio_config() checks the volume and regenerates config.json from .env if missing. 2. mkdocs-site-server (LSIO nginx) returns 403 after upgrade because the anonymous /config volume shadows the ./mkdocs/site bind mount. Fix: docker compose rm -sf the LSIO container before up -d so the anonymous volume is recreated fresh. Also adds Gancio and MkDocs site health checks to Phase 6 verification. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e3045966a0
commit
62f906d6f0
@ -26,6 +26,9 @@ CONDITIONAL_CONTAINERS="nginx code-server"
|
||||
APP_CONTAINERS="api admin media-api nginx"
|
||||
# Infrastructure containers (must stay up)
|
||||
INFRA_CONTAINERS="v2-postgres redis"
|
||||
# LSIO containers with anonymous /config volumes (must be force-recreated on upgrade
|
||||
# to prevent stale anonymous volumes from shadowing bind mounts underneath /config)
|
||||
LSIO_VOLUME_CONTAINERS="mkdocs-site-server"
|
||||
|
||||
# User-modifiable paths (auto-resolve keeps user version on conflict)
|
||||
USER_PATHS=(
|
||||
@ -106,6 +109,36 @@ restore_user_paths() {
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Verify Gancio config.json in its data volume ---
|
||||
# Gancio uses a named Docker volume for /home/node/data. If the volume loses
|
||||
# config.json (e.g., volume name prefix mismatch after compose project rename),
|
||||
# Gancio detects an existing DB but no config and refuses to start with:
|
||||
# "Non empty db! Please move your current db elsewhere than retry."
|
||||
# This regenerates config.json from .env vars when missing.
|
||||
verify_gancio_config() {
|
||||
local gancio_volume
|
||||
gancio_volume="$(docker volume ls --format '{{.Name}}' | grep 'gancio-data' | head -1 || true)"
|
||||
if [[ -z "$gancio_volume" ]]; then
|
||||
return # No gancio volume exists yet; first run will handle it
|
||||
fi
|
||||
|
||||
# Check if config.json exists and is non-empty
|
||||
if docker run --rm -v "${gancio_volume}:/data" alpine test -s /data/config.json 2>/dev/null; then
|
||||
success "Gancio config.json present in $gancio_volume"
|
||||
return
|
||||
fi
|
||||
|
||||
warn "Gancio config.json missing in volume $gancio_volume — regenerating from .env"
|
||||
local base_url="${GANCIO_BASE_URL:-https://events.cmlite.org}"
|
||||
local pg_user="${V2_POSTGRES_USER:-changemaker}"
|
||||
local pg_pass="${V2_POSTGRES_PASSWORD:-changemaker}"
|
||||
local config_json="{\"baseurl\":\"${base_url}\",\"server\":{\"host\":\"0.0.0.0\",\"port\":13120},\"db\":{\"dialect\":\"postgres\",\"host\":\"changemaker-v2-postgres\",\"port\":5432,\"database\":\"gancio\",\"username\":\"${pg_user}\",\"password\":\"${pg_pass}\"}}"
|
||||
|
||||
docker run --rm -v "${gancio_volume}:/data" alpine sh -c \
|
||||
"echo '${config_json}' > /data/config.json && chown 1000:1000 /data/config.json"
|
||||
success "Gancio config.json regenerated"
|
||||
}
|
||||
|
||||
# --- Lockfile ---
|
||||
acquire_lock() {
|
||||
if [[ -f "$LOCK_FILE" ]]; then
|
||||
@ -656,6 +689,18 @@ info "Stopping application containers..."
|
||||
docker compose stop $APP_CONTAINERS 2>/dev/null || true
|
||||
success "Application containers stopped"
|
||||
|
||||
# Force-recreate LSIO containers to prevent anonymous volume shadowing bind mounts.
|
||||
# LSIO images define a VOLUME at /config in their Dockerfile. When a container is
|
||||
# merely restarted, Docker reuses the old anonymous volume whose /config/www is empty,
|
||||
# which shadows the bind mount (e.g., ./mkdocs/site:/config/www → 403 Forbidden).
|
||||
# Removing the container first ensures a fresh anonymous volume that respects bind mounts.
|
||||
info "Removing LSIO containers (clearing anonymous volumes)..."
|
||||
docker compose rm -sf $LSIO_VOLUME_CONTAINERS 2>/dev/null || true
|
||||
success "LSIO containers cleared for fresh recreation"
|
||||
|
||||
# Verify Gancio config.json exists before starting services
|
||||
verify_gancio_config
|
||||
|
||||
# Ensure infrastructure is running and healthy
|
||||
info "Ensuring infrastructure is up..."
|
||||
docker compose up -d $INFRA_CONTAINERS
|
||||
@ -757,6 +802,28 @@ if docker ps --format '{{.Names}}' | grep -q 'changemaker-media-api'; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Gancio health (optional)
|
||||
if docker ps --format '{{.Names}}' | grep -q 'gancio-changemaker'; then
|
||||
if docker compose ps gancio --format '{{.Status}}' 2>/dev/null | grep -q "healthy"; then
|
||||
success "Gancio: healthy"
|
||||
elif docker compose ps gancio --format '{{.Status}}' 2>/dev/null | grep -qi "restarting"; then
|
||||
warn "Gancio: restart loop detected (check config.json in gancio-data volume)"
|
||||
VERIFY_FAILED=true
|
||||
else
|
||||
info "Gancio: starting (may take up to 60s)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# MkDocs static site health
|
||||
if docker ps --format '{{.Names}}' | grep -q 'mkdocs-site-server'; then
|
||||
if curl -sf http://localhost:${MKDOCS_SITE_SERVER_PORT:-4004}/ -o /dev/null 2>/dev/null; then
|
||||
success "MkDocs site (port ${MKDOCS_SITE_SERVER_PORT:-4004}): healthy"
|
||||
else
|
||||
warn "MkDocs site (port ${MKDOCS_SITE_SERVER_PORT:-4004}): not responding"
|
||||
VERIFY_FAILED=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for containers in restart loop
|
||||
RESTARTING="$(docker compose ps 2>/dev/null | grep -i "restarting" || true)"
|
||||
if [[ -n "$RESTARTING" ]]; then
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user