entrypoint.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/bash
set -e
echo "🚀 Oneirodex container starting up..."
if [[ ! -f /app/oneirodex/static/dist/member-app/member-app.js ]]; then
echo "⚠️ Warning: member-app.js not found — React member app may not load. Rebuild the Docker image to include the member-app build stage."
fi
if [[ ! -f /app/oneirodex/static/dist/member-app/member-app.css ]]; then
echo "⚠️ Warning: member-app.css not found — member SPA chrome will render unstyled. Rebuild the Docker image."
fi
if [[ ! -f /app/oneirodex/static/dist/admin-app/admin-app.js ]]; then
echo "⚠️ Warning: admin-app.js not found — React admin SPA may not load. Rebuild the Docker image."
fi
if [[ ! -f /app/oneirodex/static/dist/admin-app/admin-app.css ]]; then
echo "⚠️ Warning: admin-app.css not found — admin SPA chrome will render unstyled. Rebuild the Docker image."
fi
if [[ ! -f /app/oneirodex/static/dist/admin-pilot/index.html ]]; then
echo "❌ FastAPI admin page routes require the packaged admin-pilot/index.html bundle. Rebuild the Docker image."
exit 1
fi
if [[ ! -f /app/oneirodex/static/library/themes/default/css/od-tokens.css ]]; then
echo "⚠️ Warning: themes/default/css/od-tokens.css missing — run init or Admin → Reset Default Themes after boot."
fi
# Single-container mode: no DATABASE_URL given, so run PostgreSQL inside this
# container (docker/embedded-db.sh). The Compose stack sets DATABASE_URL and is
# unaffected.
EMBEDDED=false
# shellcheck source=docker/embedded-db.sh
source /app/docker/embedded-db.sh
if embedded_db_wanted; then
EMBEDDED=true
echo "📦 Single-container mode: using the embedded PostgreSQL (data in ${CONFIG_DIR})."
# Order matters: start_embedded_db creates ${CONFIG_DIR}/secrets and resolves
# the database user, which embedded_db_defaults needs to store SECRET_KEY.
start_embedded_db || exit 1
embedded_db_defaults
fi
# Inside Docker Compose, Postgres is the sibling service named "db".
# Never wait on localhost/127.0.0.1 (common leftover from non-Docker .env files).
if [[ "${EMBEDDED}" == "false" && -f /.dockerenv ]]; then
export DATABASE_HOST="${DATABASE_HOST:-db}"
export DATABASE_PORT="${DATABASE_PORT:-5432}"
export POSTGRES_USER="${POSTGRES_USER:-postgres}"
export POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-postgres}"
export POSTGRES_DB="${POSTGRES_DB:-oneirodex}"
# The env templates ship a placeholder, not a password. It is public (it is
# in this repo), so starting a database with it is refused outright. The
# old default `postgres` is only warned about: existing stacks rely on it.
if [[ "${POSTGRES_PASSWORD}" == CHANGE_ME* || "${DATABASE_URL}" == *":CHANGE_ME"* ]]; then
echo "❌ POSTGRES_PASSWORD is still the template placeholder. Set a strong password in .env"
echo " (e.g. openssl rand -hex 24) before the first start; see docs/runbooks/docker-compose-deploy.md."
exit 1
fi
if [[ "${POSTGRES_PASSWORD}" == "postgres" ]]; then
echo "⚠️ POSTGRES_PASSWORD is the old default 'postgres'. Rotate it (docs/runbooks/docker-compose-deploy.md)."
fi
if [[ -z "${DATABASE_URL}" \
|| "${DATABASE_URL}" == *"@localhost"* \
|| "${DATABASE_URL}" == *"@127.0.0.1"* \
|| "${DATABASE_URL}" == *"@::1"* ]]; then
export DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"
echo "ℹ️ DATABASE_URL forced to Compose service db (was empty/localhost)."
fi
fi
DB_HOST=${DATABASE_HOST:-db}
DB_USER=${POSTGRES_USER:-postgres}
DB_PORT=${DATABASE_PORT:-5432}
# Prefer parsing host from DATABASE_URL when it is not localhost
if [[ -n "$DATABASE_URL" ]]; then
PARSED_HOST=$(echo "$DATABASE_URL" | sed -n 's/.*@\([^:/]*\)[:/].*/\1/p')
PARSED_PORT=$(echo "$DATABASE_URL" | sed -n 's/.*:\([0-9][0-9]*\)\/.*/\1/p')
PARSED_USER=$(echo "$DATABASE_URL" | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
if [[ -n "$PARSED_HOST" && "$PARSED_HOST" != "localhost" && "$PARSED_HOST" != "127.0.0.1" ]]; then
DB_HOST="$PARSED_HOST"
fi
if [[ -n "$PARSED_PORT" ]]; then
DB_PORT="$PARSED_PORT"
fi
if [[ -n "$PARSED_USER" ]]; then
DB_USER="$PARSED_USER"
fi
fi
wait_for_postgres() {
echo "🔄 Waiting for PostgreSQL at ${DB_HOST}:${DB_PORT}..."
echo " DATABASE_URL host hint: $(echo "${DATABASE_URL}" | sed -E 's#://[^:]+:[^@]+@#://***:***@#')"
until python3 -c "
import os
import sys
import psycopg2
from urllib.parse import urlparse
host = os.environ.get('DATABASE_HOST', '${DB_HOST}')
port = int(os.environ.get('DATABASE_PORT', '${DB_PORT}') or 5432)
user = os.environ.get('POSTGRES_USER', '${DB_USER}')
password = os.environ.get('POSTGRES_PASSWORD', 'postgres')
database = os.environ.get('POSTGRES_DB', 'oneirodex')
url = os.environ.get('DATABASE_URL') or ''
if url:
parsed = urlparse(url)
if parsed.hostname and parsed.hostname not in ('localhost', '127.0.0.1', '::1'):
host = parsed.hostname
port = parsed.port or port
user = parsed.username or user
password = parsed.password or password
database = (parsed.path or '/oneirodex').lstrip('/') or database
else:
# Force Compose service when URL still points at loopback
host = 'db'
try:
conn = psycopg2.connect(
host=host,
port=port,
user=user,
password=password,
database=database,
connect_timeout=5,
)
conn.close()
print(f'✅ PostgreSQL connection successful ({host}:{port}/{database})')
except Exception as e:
print(f'❌ Connection failed ({host}:{port}): {e}')
sys.exit(1)
"; do
echo "⏳ PostgreSQL not ready yet, waiting 5 seconds..."
sleep 5
done
echo "✅ PostgreSQL is now available!"
}
if [[ "${EMBEDDED}" == "false" ]]; then
wait_for_postgres
echo "🎮 Starting Oneirodex Docker container..."
exec /app/startweb-docker.sh "$@"
fi
# Embedded database: stay as the parent so SIGTERM (docker stop) stops the app
# first and PostgreSQL second, cleanly, and so a dead database takes the
# container down for the restart policy to bring back.
echo "🎮 Starting Oneirodex Docker container..."
/app/startweb-docker.sh "$@" &
APP_PID=$!
shutdown() {
kill -TERM "${APP_PID}" 2>/dev/null || true
wait "${APP_PID}" 2>/dev/null || true
stop_embedded_db
exit 0
}
trap shutdown TERM INT
while kill -0 "${APP_PID}" 2>/dev/null; do
if ! embedded_db_alive; then
echo "❌ Embedded PostgreSQL stopped unexpectedly; exiting so the container restarts."
kill -TERM "${APP_PID}" 2>/dev/null || true
wait "${APP_PID}" 2>/dev/null || true
exit 1
fi
sleep 5 &
wait $! || true
done
# `set -e` is on: a bare `wait` returning the app's non-zero status would end the
# script here and skip stopping PostgreSQL, so capture the status explicitly.
APP_STATUS=0
wait "${APP_PID}" || APP_STATUS=$?
stop_embedded_db
exit "${APP_STATUS}"