L'application initialise la base elle-même : plus de scripts montés

Résout définitivement « Role sbc_app does not exist » : l'initialisation
ne dépend plus de docker-entrypoint-initdb.d ni de bind mounts du dépôt
(fragiles selon le mode de déploiement Portainer).

- Nouveau bootstrap idempotent exécuté par l'app à chaque démarrage avec
  le superuser (PG_SUPERUSER_PASSWORD) : création de la base et du rôle
  sbc_app si absents, réalignement du mot de passe, schéma en
  CREATE ... IF NOT EXISTS, données de démo si la base est vide, grants
- Schéma et seed embarqués dans l'image (server/src/sql), seed par
  recherche de noms (indépendant des séquences)
- Compose réduit à deux services (db + app), suppression de db-sync et
  du montage ./db/init ; répertoire db/ retiré

Vérifié : volume totalement vierge auto-initialisé, redémarrage sans
re-seed, changement d'APP_DB_PASSWORD auto-réparé, 34 tests e2e verts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
This commit is contained in:
Claude committed 2026-07-11 05:03:21 +00:00
1 parent 59256ad9ff
commit 4d5d42c61a
10 files changed
+181 -149

No files matched your search

+3 -22
View File
@@ -10,10 +10,8 @@ services:
# Preconfigured defaults so the stack deploys without any .env
# (Portainer, etc.). Override them in production.
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-sbc-pg-c7f3a91d284e6b05}
APP_DB_PASSWORD: ${APP_DB_PASSWORD:-sbc-app-9e12d47ab8c3f605}
volumes:
- db_data:/var/lib/postgresql/data
- ./db/init:/docker-entrypoint-initdb.d:ro
ports:
# Loopback only: reachable from the host machine (psql, backups),
# never from the network. Remove this mapping to close it entirely.
@@ -30,24 +28,6 @@ services:
timeout: 3s
retries: 12
# One-shot at every stack start: realigns the sbc_app role password with
# APP_DB_PASSWORD, healing volumes initialized with an older value.
db-sync:
image: postgres:16-alpine
restart: "no"
depends_on:
db:
condition: service_healthy
environment:
PGHOST: sbc-db
PGUSER: postgres
PGDATABASE: sbc
PGPASSWORD: ${POSTGRES_PASSWORD:-sbc-pg-c7f3a91d284e6b05}
APP_DB_PASSWORD: ${APP_DB_PASSWORD:-sbc-app-9e12d47ab8c3f605}
volumes:
- ./db/sync-app-role.sh:/sync-app-role.sh:ro
entrypoint: ["/bin/sh", "/sync-app-role.sh"]
app:
build: .
restart: unless-stopped
@@ -61,6 +41,9 @@ services:
PGDATABASE: sbc
PGUSER: sbc_app
PGPASSWORD: ${APP_DB_PASSWORD:-sbc-app-9e12d47ab8c3f605}
# Lets the app bootstrap the database itself at every startup
# (role, schema, demo data) — fully idempotent, heals any volume state.
PG_SUPERUSER_PASSWORD: ${POSTGRES_PASSWORD:-sbc-pg-c7f3a91d284e6b05}
# Empty by default: the app then generates a random ephemeral secret at
# startup. Set a fixed value to keep sessions across restarts.
JWT_SECRET: ${JWT_SECRET:-}
@@ -82,8 +65,6 @@ services:
depends_on:
db:
condition: service_healthy
db-sync:
condition: service_completed_successfully
read_only: true
tmpfs:
- /tmp