Add idempotent Postgres initialization service for app-specific roles and databases. Update .env.example and docker-compose.yaml accordingly.

This commit is contained in:
emelinda 2026-07-23 15:13:11 +03:00
parent 83a8339db7
commit 2c3fce7834
4 changed files with 74 additions and 10 deletions

View File

@ -9,12 +9,16 @@ K3S_API_HOST=10.0.0.10
SAREX_POSTGRES_DB=sarex_db SAREX_POSTGRES_DB=sarex_db
SAREX_POSTGRES_USER=sarex SAREX_POSTGRES_USER=sarex
SAREX_POSTGRES_PASSWORD=sarex SAREX_POSTGRES_PASSWORD=sarex
# Отдельные роли приложений с паролями (создаются init-скриптом postgres). # Отдельные роли приложений с паролями (создаются контейнером postgres-init).
# Приложения ходят в БД под ними, а не под суперпользователем. Без одинарных кавычек. # Приложения ходят в БД под ними, а не под суперпользователем. Без одинарных кавычек.
SAREX_DJANGO_DB_USER=django SAREX_DJANGO_DB_USER=django
SAREX_DJANGO_DB_PASSWORD=django-secret SAREX_DJANGO_DB_PASSWORD=django-secret
SAREX_PROCESSING_DB_USER=processing SAREX_PROCESSING_DB_USER=processing
SAREX_PROCESSING_DB_PASSWORD=processing-secret SAREX_PROCESSING_DB_PASSWORD=processing-secret
SAREX_BIM_DB_USER=bim
SAREX_BIM_DB_PASSWORD=bim-secret
SAREX_WORKSPACE_DB_USER=workspace
SAREX_WORKSPACE_DB_PASSWORD=workspace-secret
SAREX_RABBITMQ_VHOST=api SAREX_RABBITMQ_VHOST=api
SAREX_RABBITMQ_USER=rabbit SAREX_RABBITMQ_USER=rabbit
SAREX_RABBITMQ_PASSWORD=rabbit SAREX_RABBITMQ_PASSWORD=rabbit
@ -39,8 +43,12 @@ MINIO_DOMAIN=minio.sarex.local # MinIO: S3 API (/) + консоль (/con
SAREX_BACKEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/sarex-backend-dev:latest SAREX_BACKEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/sarex-backend-dev:latest
SAREX_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/sarex-frontend-dev:latest SAREX_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/sarex-frontend-dev:latest
# Приложение processing (workflows-api + workflows-frontend) # Базы данных приложений (django использует SAREX_POSTGRES_DB)
SAREX_PROCESSING_DB=workflow_db SAREX_PROCESSING_DB=workflow_db
SAREX_BIM_DB=bim_db
SAREX_WORKSPACE_DB=workspace_db
# Приложение processing (workflows-api + workflows-frontend)
SAREX_PROCESSING_API_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-api_prod:075fc0 SAREX_PROCESSING_API_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-api_prod:075fc0
SAREX_PROCESSING_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c SAREX_PROCESSING_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c

View File

@ -20,6 +20,8 @@ sarex_secret_vars:
- SAREX_POSTGRES_PASSWORD - SAREX_POSTGRES_PASSWORD
- SAREX_DJANGO_DB_PASSWORD - SAREX_DJANGO_DB_PASSWORD
- SAREX_PROCESSING_DB_PASSWORD - SAREX_PROCESSING_DB_PASSWORD
- SAREX_BIM_DB_PASSWORD
- SAREX_WORKSPACE_DB_PASSWORD
- SAREX_RABBITMQ_PASSWORD - SAREX_RABBITMQ_PASSWORD
- SAREX_MINIO_ROOT_PASSWORD - SAREX_MINIO_ROOT_PASSWORD
- SAREX_MINIO_APP_PASSWORD - SAREX_MINIO_APP_PASSWORD

View File

@ -23,13 +23,6 @@
dest: "{{ deploy_dir }}/nginx/templates/" dest: "{{ deploy_dir }}/nginx/templates/"
mode: "0644" mode: "0644"
# postgres монтирует ./postgres/initdb (создаёт роли/БД на пустом томе)
- name: Скопировать init-скрипты postgres
ansible.builtin.copy:
src: "{{ deploy_src_root }}/postgres/initdb/"
dest: "{{ deploy_dir }}/postgres/initdb/"
mode: "0755"
# --- Секреты: генерация с персистом на control-node (идемпотентно) -------- # --- Секреты: генерация с персистом на control-node (идемпотентно) --------
- name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored) - name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored)
ansible.builtin.set_fact: ansible.builtin.set_fact:

View File

@ -106,7 +106,6 @@ services:
PROC_DB_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret} PROC_DB_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret}
volumes: volumes:
- sarex-postgres-data:/var/lib/postgresql/data - sarex-postgres-data:/var/lib/postgresql/data
- ./postgres/initdb:/docker-entrypoint-initdb.d:ro,z # создаёт workflow_db (только на пустом томе)
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${SAREX_POSTGRES_USER:-sarex} -d ${SAREX_POSTGRES_DB:-sarex_db}"] test: ["CMD-SHELL", "pg_isready -U ${SAREX_POSTGRES_USER:-sarex} -d ${SAREX_POSTGRES_DB:-sarex_db}"]
interval: 10s interval: 10s
@ -114,6 +113,62 @@ services:
retries: 12 retries: 12
start_period: 10s start_period: 10s
# Одноразовый init: на каждое приложение заводит роль (LOGIN+пароль) и базу
# данных с этим владельцем. Идемпотентно (по образцу minio-init).
postgres-init:
image: postgres:12-alpine
depends_on:
postgres:
condition: service_healthy
entrypoint:
- /bin/sh
- -c
- |
set -e
until psql -h postgres -U "$$SUPER_USER" -d "$$SUPER_DB" -c 'SELECT 1' >/dev/null 2>&1; do
echo 'waiting for postgres...'; sleep 2;
done
q() { psql -v ON_ERROR_STOP=1 -h postgres -U "$$SUPER_USER" -d "$$SUPER_DB" "$$@"; }
# provision <db> <user> <password>
provision() {
q -tc "SELECT 1 FROM pg_roles WHERE rolname='$$2'" | grep -q 1 \
|| q -c "CREATE ROLE \"$$2\" LOGIN PASSWORD '$$3'"
q -c "ALTER ROLE \"$$2\" WITH LOGIN PASSWORD '$$3'"
q -tc "SELECT 1 FROM pg_database WHERE datname='$$1'" | grep -q 1 \
|| q -c "CREATE DATABASE \"$$1\" OWNER \"$$2\""
q -c "ALTER DATABASE \"$$1\" OWNER TO \"$$2\""
q -c "GRANT ALL PRIVILEGES ON DATABASE \"$$1\" TO \"$$2\""
echo "db $$1 + user $$2 ready"
}
provision "$$DJANGO_DB" "$$DJANGO_USER" "$$DJANGO_PASSWORD"
provision "$$PROC_DB" "$$PROC_USER" "$$PROC_PASSWORD"
provision "$$BIM_DB" "$$BIM_USER" "$$BIM_PASSWORD"
provision "$$WORKSPACE_DB" "$$WORKSPACE_USER" "$$WORKSPACE_PASSWORD"
environment:
PGPASSWORD: ${SAREX_POSTGRES_PASSWORD:-sarex}
SUPER_USER: ${SAREX_POSTGRES_USER:-sarex}
SUPER_DB: ${SAREX_POSTGRES_DB:-sarex_db}
# django (использует основную базу SAREX_POSTGRES_DB)
DJANGO_DB: ${SAREX_POSTGRES_DB:-sarex_db}
DJANGO_USER: ${SAREX_DJANGO_DB_USER:-django}
DJANGO_PASSWORD: ${SAREX_DJANGO_DB_PASSWORD:-django-secret}
# processing
PROC_DB: ${SAREX_PROCESSING_DB:-workflow_db}
PROC_USER: ${SAREX_PROCESSING_DB_USER:-processing}
PROC_PASSWORD: ${SAREX_PROCESSING_DB_PASSWORD:-processing-secret}
# bim
BIM_DB: ${SAREX_BIM_DB:-bim_db}
BIM_USER: ${SAREX_BIM_DB_USER:-bim}
BIM_PASSWORD: ${SAREX_BIM_DB_PASSWORD:-bim-secret}
# workspace
WORKSPACE_DB: ${SAREX_WORKSPACE_DB:-workspace_db}
WORKSPACE_USER: ${SAREX_WORKSPACE_DB_USER:-workspace}
WORKSPACE_PASSWORD: ${SAREX_WORKSPACE_DB_PASSWORD:-workspace-secret}
restart: "no"
redis: redis:
image: cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10 image: cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10
container_name: redis container_name: redis
@ -236,6 +291,8 @@ services:
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
postgres-init:
condition: service_completed_successfully
redis: redis:
condition: service_healthy condition: service_healthy
rabbitmq: rabbitmq:
@ -253,6 +310,8 @@ services:
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
postgres-init:
condition: service_completed_successfully
redis: redis:
condition: service_healthy condition: service_healthy
rabbitmq: rabbitmq:
@ -297,6 +356,8 @@ services:
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
postgres-init:
condition: service_completed_successfully
processing-frontend: processing-frontend:
image: ${SAREX_PROCESSING_FRONTEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c} image: ${SAREX_PROCESSING_FRONTEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/workflows-frontend:ugok2_85f6ce2c}