From 316bc81a4ca345d8ba39017e2ce7ba514271bab3 Mon Sep 17 00:00:00 2001 From: Proudlock <270015376@geaerospace.com> Date: Sun, 6 Sep 2026 23:01:06 -0400 Subject: [PATCH] Add automatic plugin installation on first Docker deployment - Add docker-entrypoint.sh: runs migrations and bootstraps plugins - Add bootstrap-plugins.sh: installs all plugins (disabled by default) - Update Dockerfile to use entrypoint - Plugins can now be enabled via Settings UI after first deployment - Idempotent: safe to run multiple times - Solves issue where imported prod databases had tables but no plugin registry --- Dockerfile | 6 ++++++ scripts/bootstrap-plugins.sh | 27 +++++++++++++++++++++++++++ scripts/docker-entrypoint.sh | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 scripts/bootstrap-plugins.sh create mode 100644 scripts/docker-entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 7d7c4242..f5ed2ae6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -123,6 +123,9 @@ COPY migrations/ ./migrations/ COPY scripts/ ./scripts/ COPY wsgi.py ./ +# Make entrypoint and bootstrap scripts executable +RUN chmod +x /app/scripts/docker-entrypoint.sh /app/scripts/bootstrap-plugins.sh + # Built SPA from stage 1. Flask serves it via register_frontend_routes. COPY --from=frontendbuild /build/frontend/dist ./frontend/dist @@ -139,6 +142,9 @@ USER shopdb EXPOSE 5001 +# Entrypoint runs migrations and bootstraps plugins on first deployment +ENTRYPOINT ["/app/scripts/docker-entrypoint.sh"] + # Probe the public health route, not the login endpoint. Probing POST # /api/auth/login logged a 400 every 30s and ran the credential path from a # health check. The route answers 200 even when the database is degraded, so the diff --git a/scripts/bootstrap-plugins.sh b/scripts/bootstrap-plugins.sh new file mode 100644 index 00000000..7a8e4e67 --- /dev/null +++ b/scripts/bootstrap-plugins.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Bootstrap plugin installation on first deployment. +# Installs all available plugins but leaves them disabled, so admins can +# enable what they need via Settings UI. Idempotent: safe to run multiple times. + +set -e + +REGISTRY_FILE="/app/instance/plugins.json" + +if [ ! -f "$REGISTRY_FILE" ]; then + echo "==> First deployment detected: installing all available plugins (disabled by default)" + + # Get list of all available plugins + PLUGINS=$(flask plugin list 2>/dev/null | grep -E '^\s+\w+\s+v[0-9]' | awk '{print $1}') + + for plugin in $PLUGINS; do + echo " Installing $plugin..." + flask plugin install "$plugin" || { + echo " WARNING: Failed to install $plugin, skipping" + continue + } + done + + echo "==> All plugins installed (disabled). Enable them in Settings > Plugins" +else + echo "==> Plugin registry exists, skipping bootstrap" +fi diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh new file mode 100644 index 00000000..550f2b5e --- /dev/null +++ b/scripts/docker-entrypoint.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Docker container entrypoint for ShopDB Flask. +# Runs migrations, bootstraps plugins on first deployment, then starts the app. + +set -e + +echo "==> ShopDB Flask Container Starting" + +# Wait for database to be ready (optional, useful with docker-compose) +if [ -n "$DATABASE_URL" ]; then + echo "==> Waiting for database..." + for i in {1..30}; do + if flask db current &>/dev/null; then + echo "==> Database ready" + break + fi + echo " Attempt $i/30: database not ready, waiting..." + sleep 2 + done +fi + +# Run migrations +echo "==> Running database migrations" +flask db upgrade || { + echo "ERROR: Database migrations failed" + exit 1 +} + +# Bootstrap plugins on first deployment +echo "==> Checking plugin installation" +/app/scripts/bootstrap-plugins.sh + +echo "==> Starting application" +exec "$@"