feat(deploy): inline bootstrap into db-init — compose is the single source; DB_PORT everywhere
z_rls_role.sh is gone. The db-init service carries the bootstrap SQL
inline (the script's docker-exec/local-socket mode was its only reason
to exist as a file, and the no-clone deployment path could not use it:
docker bind-mounts of missing host paths auto-create empty DIRECTORIES,
so a compose-only install got '/z_rls_role.sh: no such file').
The inline form surfaced two silent bugs the script had masked:
- psql defaulted its DATABASE to the username (POSTGRES_DB is not a
libpq variable) — the ownership loop ran against 'postgres' and
no-opped on existing volumes. Fixed with PGDATABASE: bookhoard.
- PGPORT was never propagated: with a custom DB_PORT, db-init dialed
5432 while Postgres listened on the custom port. Fixed with
PGPORT: ${DB_PORT:-5432} — DB_PORT is now a variable in every
connection path (db listener, host mappings, app, db-init).
Also removed the db service's initdb.d mount: the app executes the full
schema as the runtime-role owner on every boot incl. first (pg_trgm is
a trusted extension; the db owner can create it), so the bootstrap SQL
was its only content.
Verified: dev two-boot against the existing 40-table volume (owners
converged, 0 off-owner tables/functions), custom-port throwaway
(DB_PORT=15432: db-init + app both on the custom port, healthy),
default-port throwaway (fresh volume, healthy), full Go suite green.
Manual repair path: docker compose run --rm db-init.
This commit is contained in:
1 parent
cf73eec2e4
commit
304ea9599f
4 files changed
+73
-90
No files matched your search
@@ -69,14 +69,42 @@ services:
|
||||
image: postgres:15-alpine
|
||||
container_name: bookhoard_db_init
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: bookhoard
|
||||
PGHOST: db
|
||||
DBPASS: ${DBPASS}
|
||||
PGUSER: postgres
|
||||
PGDATABASE: bookhoard
|
||||
PGPASSWORD: ${DBPASS}
|
||||
DBSRVPASS: ${DBSRVPASS}
|
||||
volumes:
|
||||
- ./database/schema/z_rls_role.sh:/z_rls_role.sh:ro
|
||||
command: bash /z_rls_role.sh
|
||||
entrypoint: ["bash", "-c"]
|
||||
command:
|
||||
- |
|
||||
set -e
|
||||
: "${DBSRVPASS:?DBSRVPASS required in .env}"
|
||||
psql -v ON_ERROR_STOP=1 -v role_pass="$DBSRVPASS" <<'EOSQL'
|
||||
DO $$$$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'bookhoard_srv') THEN
|
||||
CREATE ROLE bookhoard_srv LOGIN;
|
||||
END IF;
|
||||
END $$$$;
|
||||
ALTER ROLE bookhoard_srv LOGIN PASSWORD :'role_pass';
|
||||
DO $$$$
|
||||
DECLARE r RECORD;
|
||||
BEGIN
|
||||
FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP
|
||||
EXECUTE format('ALTER TABLE public.%I OWNER TO bookhoard_srv', r.tablename);
|
||||
END LOOP;
|
||||
FOR r IN SELECT sequencename FROM pg_sequences WHERE schemaname = 'public' LOOP
|
||||
EXECUTE format('ALTER SEQUENCE public.%I OWNER TO bookhoard_srv', r.sequencename);
|
||||
END LOOP;
|
||||
FOR r IN SELECT p.oid::regprocedure AS fn FROM pg_proc p
|
||||
JOIN pg_namespace n ON p.pronamespace = n.oid
|
||||
WHERE n.nspname = 'public' AND p.prokind = 'f' LOOP
|
||||
EXECUTE format('ALTER FUNCTION %s OWNER TO bookhoard_srv', r.fn);
|
||||
END LOOP;
|
||||
END $$$$;
|
||||
ALTER SCHEMA public OWNER TO bookhoard_srv;
|
||||
ALTER DATABASE bookhoard OWNER TO bookhoard_srv;
|
||||
EOSQL
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
Reference in new issue
Block a user