docs(prod): репа догоняет новую раскладку postgres на prod-vm
Some checks failed
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Public / Build + push Public (test + latest) (push) Has been cancelled
Docker Web / Build + push Web (push) Has been cancelled
Docker Public / Deploy :test → test.food-market.kz (push) Has been cancelled
Docker Web / Deploy Web on stage (push) Has been cancelled
Some checks failed
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Public / Build + push Public (test + latest) (push) Has been cancelled
Docker Web / Build + push Web (push) Has been cancelled
Docker Public / Deploy :test → test.food-market.kz (push) Has been cancelled
Docker Web / Deploy Web on stage (push) Has been cancelled
05.10.2026 общий postgres-инстанс с чужими боевыми базами (sklad, purchase, calcman, calcman_staging, makesales + мусорная старая food_market) вынесен из compose прода food-market в отдельный compose-проект shared-postgres (контейнер shared-postgres, порт 5434, том food-market-postgres-data external). Прод food-market поднимается в собственный контейнер food-market-prod-postgres (порт 5437, том food-market-prod-postgres-data). Простой при разделении — 12с, соседи живы. См. docs/shared-postgres-followup-progress.md. Этот коммит синхронизирует репозиторий, чтобы следующий деплой из main не воскресил старую раскладку: - deploy/docker-compose.yml: container_name/port/volume приведены к прод-файлу (food-market-prod-postgres, 127.0.0.1:5437, food-market-prod-postgres-data). - deploy/shared-postgres/ (новое): документационная копия соседнего compose'а, с явной пометкой «food-market им не управляет». - deploy/food-market-backup.sh / anonymize-prod.sh / db-schema-diff.sh: defaults FM_PG_CONTAINER / FM_PROD_CONT = food-market-prod-postgres. - docs/RUNBOOK.md: новый раздел «Postgres на prod-vm» с таблицей трёх инстансов и явным запретом трогать shared-postgres из наших скриптов. - docs/backup-restore.md: контейнер в таблице и примерах — новый. Guards (не в репе — живут в ~/deploy-stage.sh и ~/quality-watchdog.sh) расширены симметрично: стенду запрещены shared-postgres, food-market-prod- postgres[-data], 5434/5437; проду — food-market-postgres-data (чужие данные). Проверка: docker compose config/ps на prod-vm shared-postgres не упоминают, grep по репе — ни один скрипт не делает docker exec в shared-postgres.
This commit is contained in:
parent
ef29acb0d1
commit
c4a59d7bf2
|
|
@ -21,14 +21,18 @@
|
||||||
# deploy/anonymize-prod.sh [--source <conn-uri>] [--target <conn-uri>]
|
# deploy/anonymize-prod.sh [--source <conn-uri>] [--target <conn-uri>]
|
||||||
# [--out <file>] [--dry-run]
|
# [--out <file>] [--dry-run]
|
||||||
#
|
#
|
||||||
# Default source: ssh prod docker exec food-market-postgres pg_dump
|
# Default source: ssh prod docker exec food-market-prod-postgres pg_dump
|
||||||
# Default target: local postgres@14 with TEMP DB food_market_anon
|
# Default target: local postgres@14 with TEMP DB food_market_anon
|
||||||
# Default out: /home/nns/food-market-anon-YYYYMMDD.sql.gz
|
# Default out: /home/nns/food-market-anon-YYYYMMDD.sql.gz
|
||||||
|
#
|
||||||
|
# ВАЖНО: контейнер food-market-prod-postgres (с 2026-10-05). НЕ shared-postgres —
|
||||||
|
# тот принадлежит соседнему compose-проекту с чужими боевыми базами (sklad,
|
||||||
|
# purchase, calcman, calcman_staging, makesales). См. docs/shared-postgres-followup-progress.md.
|
||||||
|
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
SOURCE_HOST="${FM_PROD_HOST:-nns@admin.food-market.kz}"
|
SOURCE_HOST="${FM_PROD_HOST:-nns@admin.food-market.kz}"
|
||||||
SOURCE_CONTAINER="${FM_PROD_CONT:-food-market-postgres}"
|
SOURCE_CONTAINER="${FM_PROD_CONT:-food-market-prod-postgres}"
|
||||||
SOURCE_DB="${FM_PG_DB:-food_market}"
|
SOURCE_DB="${FM_PG_DB:-food_market}"
|
||||||
SOURCE_USER="${FM_PG_USER:-food_market}"
|
SOURCE_USER="${FM_PG_USER:-food_market}"
|
||||||
LOCAL_USER="${PGUSER:-nns}"
|
LOCAL_USER="${PGUSER:-nns}"
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,13 @@
|
||||||
#
|
#
|
||||||
# Подразумевает что обе БД доступны (например через SSH-туннель или
|
# Подразумевает что обе БД доступны (например через SSH-туннель или
|
||||||
# pg_dump --host=<host>). Дефолтные подключения:
|
# pg_dump --host=<host>). Дефолтные подключения:
|
||||||
# stage = docker exec food-market-stage-postgres-1 pg_dump (через ssh dev-vm)
|
# stage = docker exec food-market-stage-postgres pg_dump (через ssh prod-vm)
|
||||||
# prod = docker exec food-market-postgres pg_dump (через ssh prod-vm)
|
# prod = docker exec food-market-prod-postgres pg_dump (через ssh prod-vm)
|
||||||
|
#
|
||||||
|
# ВАЖНО: прод-контейнер — `food-market-prod-postgres` (с 2026-10-05). Соседний
|
||||||
|
# `shared-postgres` на той же машине обслуживает ЧУЖИЕ боевые базы (sklad,
|
||||||
|
# purchase, calcman, calcman_staging, makesales) и в diff не участвует.
|
||||||
|
# См. docs/shared-postgres-followup-progress.md.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# deploy/db-schema-diff.sh [--stage-host HOST] [--prod-host HOST]
|
# deploy/db-schema-diff.sh [--stage-host HOST] [--prod-host HOST]
|
||||||
|
|
@ -24,8 +29,8 @@ set -uo pipefail
|
||||||
|
|
||||||
STAGE_HOST="${FM_STAGE_HOST:-nns@192.168.1.190}"
|
STAGE_HOST="${FM_STAGE_HOST:-nns@192.168.1.190}"
|
||||||
PROD_HOST="${FM_PROD_HOST:-nns@admin.food-market.kz}"
|
PROD_HOST="${FM_PROD_HOST:-nns@admin.food-market.kz}"
|
||||||
STAGE_CONT="${FM_STAGE_CONT:-food-market-stage-postgres-1}"
|
STAGE_CONT="${FM_STAGE_CONT:-food-market-stage-postgres}"
|
||||||
PROD_CONT="${FM_PROD_CONT:-food-market-postgres}"
|
PROD_CONT="${FM_PROD_CONT:-food-market-prod-postgres}"
|
||||||
DB="${FM_PG_DB:-food_market}"
|
DB="${FM_PG_DB:-food_market}"
|
||||||
DB_USER="${FM_PG_USER:-food_market}"
|
DB_USER="${FM_PG_USER:-food_market}"
|
||||||
QUICK=0
|
QUICK=0
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,32 @@
|
||||||
|
# Прод-compose food-market.
|
||||||
|
#
|
||||||
|
# ВАЖНО (2026-10-05): у food-market свой postgres прода — контейнер
|
||||||
|
# `food-market-prod-postgres`, том `food-market-prod-postgres-data`, порт
|
||||||
|
# `127.0.0.1:5437`. На prod-vm параллельно существует отдельный compose-проект
|
||||||
|
# `shared-postgres` (~/shared-postgres/docker-compose.yml, порт 5434, том
|
||||||
|
# `food-market-postgres-data` *external*) с ЧУЖИМИ боевыми базами (sklad,
|
||||||
|
# purchase, calcman, calcman_staging, makesales). Он food-market НЕ принадлежит
|
||||||
|
# и в этот compose возвращаться НЕ должен. См. docs/shared-postgres-followup-progress.md.
|
||||||
|
#
|
||||||
|
# Guards в ~/deploy-stage.sh и ~/quality-watchdog.sh падают, если здесь появится
|
||||||
|
# `shared-postgres`, `food-market-postgres-data`, порт `5434` или старое имя
|
||||||
|
# контейнера `food-market-postgres`.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: ${REGISTRY:-127.0.0.1:5001}/mirror/postgres:16-alpine
|
image: ${REGISTRY:-127.0.0.1:5001}/mirror/postgres:16-alpine
|
||||||
container_name: food-market-postgres
|
container_name: food-market-prod-postgres
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: food_market
|
POSTGRES_DB: food_market
|
||||||
POSTGRES_USER: food_market
|
POSTGRES_USER: food_market
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-food_market_dev}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-food_market_dev}
|
||||||
PGDATA: /var/lib/postgresql/data/pgdata
|
PGDATA: /var/lib/postgresql/data/pgdata
|
||||||
# Stage VM already uses 5432 (host postgres) — map ours to 5434 to avoid clash.
|
# prod-vm занят: 5432 — host postgres, 5434 — shared-postgres (чужой),
|
||||||
|
# 5435 — stage-postgres, 5436 — food-market-server-postgres (сосед).
|
||||||
|
# Нам остаётся 5437.
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:5434:5432"
|
- "127.0.0.1:5437:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres-data:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
@ -88,7 +104,9 @@ services:
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres-data:
|
postgres-data:
|
||||||
name: food-market-postgres-data
|
# ВАЖНО: НЕ `food-market-postgres-data` — тот том принадлежит отдельному
|
||||||
|
# проекту shared-postgres (чужие боевые базы). См. docs/shared-postgres-followup-progress.md.
|
||||||
|
name: food-market-prod-postgres-data
|
||||||
api-data:
|
api-data:
|
||||||
name: food-market-api-data
|
name: food-market-api-data
|
||||||
api-logs:
|
api-logs:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# food-market: ежедневный бэкап БД + загруженных файлов с ротацией.
|
# food-market: ежедневный бэкап БД + загруженных файлов с ротацией.
|
||||||
#
|
#
|
||||||
# Дампит Postgres (контейнер food-market-postgres) в custom-формат pg_dump
|
# Дампит Postgres (контейнер food-market-prod-postgres) в custom-формат pg_dump
|
||||||
# (-Fc, пригоден для pg_restore с параллелизмом/выборочным восстановлением) и
|
# (-Fc, пригоден для pg_restore с параллелизмом/выборочным восстановлением) и
|
||||||
# архивирует каталог uploads. Удаляет бэкапы старше RETENTION_DAYS дней.
|
# архивирует каталог uploads. Удаляет бэкапы старше RETENTION_DAYS дней.
|
||||||
#
|
#
|
||||||
|
|
@ -10,16 +10,19 @@
|
||||||
# вручную. Конфигурируется переменными окружения (значения по умолчанию
|
# вручную. Конфигурируется переменными окружения (значения по умолчанию
|
||||||
# совпадают с deploy/docker-compose.yml):
|
# совпадают с deploy/docker-compose.yml):
|
||||||
#
|
#
|
||||||
# FM_PG_CONTAINER имя контейнера Postgres (food-market-postgres)
|
# FM_PG_CONTAINER имя контейнера Postgres (food-market-prod-postgres)
|
||||||
# FM_PG_DB имя БД (food_market)
|
# FM_PG_DB имя БД (food_market)
|
||||||
# FM_PG_USER пользователь БД (food_market)
|
# FM_PG_USER пользователь БД (food_market)
|
||||||
# FM_BACKUP_DIR куда складывать бэкапы (/opt/food-market-data/backups)
|
# FM_BACKUP_DIR куда складывать бэкапы (/opt/food-market-data/backups)
|
||||||
# FM_UPLOADS_DIR каталог изображений (/opt/food-market-data/uploads)
|
# FM_UPLOADS_DIR каталог изображений (/opt/food-market-data/uploads)
|
||||||
# FM_BACKUP_RETENTION_DAYS срок хранения, дней (30)
|
# FM_BACKUP_RETENTION_DAYS срок хранения, дней (30)
|
||||||
#
|
#
|
||||||
|
# ВАЖНО: НЕ `food-market-postgres` и НЕ `shared-postgres` — это контейнер
|
||||||
|
# соседнего compose-проекта с ЧУЖИМИ боевыми базами (sklad, purchase, calcman,
|
||||||
|
# calcman_staging, makesales). См. docs/shared-postgres-followup-progress.md.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
CONTAINER="${FM_PG_CONTAINER:-food-market-postgres}"
|
CONTAINER="${FM_PG_CONTAINER:-food-market-prod-postgres}"
|
||||||
DB="${FM_PG_DB:-food_market}"
|
DB="${FM_PG_DB:-food_market}"
|
||||||
DB_USER="${FM_PG_USER:-food_market}"
|
DB_USER="${FM_PG_USER:-food_market}"
|
||||||
BACKUP_DIR="${FM_BACKUP_DIR:-/opt/food-market-data/backups}"
|
BACKUP_DIR="${FM_BACKUP_DIR:-/opt/food-market-data/backups}"
|
||||||
|
|
|
||||||
17
deploy/shared-postgres/README.md
Normal file
17
deploy/shared-postgres/README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# deploy/shared-postgres/
|
||||||
|
|
||||||
|
Снимок стороннего compose-проекта `shared-postgres` с prod-vm, положенный в репу
|
||||||
|
как справочник. **Food-market этим compose'ом не управляет** — он живёт на
|
||||||
|
prod-vm в `~/shared-postgres/` и там же обслуживается. Любой скрипт food-market,
|
||||||
|
который трогает `shared-postgres`, том `food-market-postgres-data`, порт 5434 —
|
||||||
|
баг (guards падают).
|
||||||
|
|
||||||
|
Контекст: 2026-10-05 общий postgres-инстанс с чужими боевыми базами (`sklad`,
|
||||||
|
`purchase`, `calcman`, `calcman_staging`, `makesales` + мусорная старая
|
||||||
|
`food_market`) вынесен из compose прода food-market в отдельный compose-проект.
|
||||||
|
См. [`docs/shared-postgres-followup-progress.md`](../../docs/shared-postgres-followup-progress.md)
|
||||||
|
и [`docs/RUNBOOK.md`](../../docs/RUNBOOK.md) → раздел «Postgres на prod-vm».
|
||||||
|
|
||||||
|
Прод food-market ходит в **свой** postgres: `food-market-prod-postgres`,
|
||||||
|
том `food-market-prod-postgres-data`, порт `127.0.0.1:5437` — описан в
|
||||||
|
`deploy/docker-compose.yml`.
|
||||||
50
deploy/shared-postgres/docker-compose.yml
Normal file
50
deploy/shared-postgres/docker-compose.yml
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────
|
||||||
|
# shared-postgres: ДОКУМЕНТАЦИОННАЯ копия стороннего compose'а на prod-vm.
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────
|
||||||
|
#
|
||||||
|
# Этот файл **не используется** ни одним из скриптов репозитория. Он лежит в
|
||||||
|
# репе как справочник: именно так на prod-vm выглядит compose-проект
|
||||||
|
# `shared-postgres`, живущий в `~/shared-postgres/docker-compose.yml`.
|
||||||
|
#
|
||||||
|
# Что это такое. С 2026-10-05 общий postgres-инстанс (чужие боевые базы
|
||||||
|
# `sklad`, `purchase`, `calcman`, `calcman_staging`, `makesales`, плюс
|
||||||
|
# мусорная старая `food_market` — повреждена, не восстанавливается) вынесен
|
||||||
|
# из compose прода food-market в отдельный compose-проект. Раньше он жил в
|
||||||
|
# том же `~/food-market/deploy/docker-compose.yml` под project-name `deploy`,
|
||||||
|
# и любой `docker compose down` у food-market гасил чужие боевые базы.
|
||||||
|
#
|
||||||
|
# Проект называется `shared-postgres`, контейнер — `shared-postgres`, порт —
|
||||||
|
# `127.0.0.1:5434`, том `food-market-postgres-data` объявлен *external*
|
||||||
|
# (имя историческое — на нём лежат чужие продакшн-данные соседних систем,
|
||||||
|
# переименовывать нельзя).
|
||||||
|
#
|
||||||
|
# **Food-market НЕ управляет этим compose.** Любые наши скрипты (backup,
|
||||||
|
# anonymize, schema-diff, deploy, watchdog), включая `docker exec`, не должны
|
||||||
|
# ссылаться на `shared-postgres` / `food-market-postgres-data` / порт 5434 —
|
||||||
|
# за этим следят guards в ~/deploy-stage.sh и ~/quality-watchdog.sh.
|
||||||
|
#
|
||||||
|
# Нужен dump/бэкап чужой базы — делает её владелец у себя. См.
|
||||||
|
# docs/shared-postgres-followup-progress.md и docs/RUNBOOK.md.
|
||||||
|
|
||||||
|
name: shared-postgres
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: 192.168.1.193:5001/mirror/postgres:16-alpine
|
||||||
|
container_name: shared-postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .env
|
||||||
|
environment:
|
||||||
|
PGDATA: /var/lib/postgresql/data/pgdata
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5434:5432"
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
|
external: true
|
||||||
|
name: food-market-postgres-data
|
||||||
|
|
@ -87,6 +87,37 @@ Nginx внутри контейнера сделан с `absolute_redirect off;
|
||||||
off;` — иначе 301 с `/signup` на `/signup/` строился через HTTP-schema и
|
off;` — иначе 301 с `/signup` на `/signup/` строился через HTTP-schema и
|
||||||
браузер уходил с https → http. См. `src/food-market.public/deploy/nginx.conf`.
|
браузер уходил с https → http. См. `src/food-market.public/deploy/nginx.conf`.
|
||||||
|
|
||||||
|
## Postgres на prod-vm
|
||||||
|
|
||||||
|
На prod-vm (`admin.food-market.kz`, `192.168.1.190`) **три** Postgres-контейнера.
|
||||||
|
Food-market владеет только одним из них — остальные **нельзя** трогать нашими
|
||||||
|
скриптами, бэкапами, миграциями или `docker exec`.
|
||||||
|
|
||||||
|
| Контейнер | Compose-проект | Том | Порт | Чьи данные |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `food-market-prod-postgres` | `food-market` (`~/food-market/deploy/`) | `food-market-prod-postgres-data` | `127.0.0.1:5437` | **наш прод** |
|
||||||
|
| `food-market-stage-postgres` | `food-market-stage` (`~/food-market-stage/deploy/`) | `food-market-stage-postgres-data` | `127.0.0.1:5435` | наш стенд |
|
||||||
|
| `shared-postgres` | `shared-postgres` (`~/shared-postgres/`) | `food-market-postgres-data` *external* | `127.0.0.1:5434` | **НЕ наш** — чужие боевые базы `sklad`, `purchase`, `calcman`, `calcman_staging`, `makesales`, плюс мусорная старая `food_market` (повреждена, не восстанавливаем) |
|
||||||
|
|
||||||
|
Истоpически (до 2026-10-05) все эти базы жили в одном compose-проекте food-market
|
||||||
|
под именем контейнера `food-market-postgres` / томом `food-market-postgres-data`.
|
||||||
|
Любой `docker compose down` у food-market гасил чужие боевые базы. Координатор
|
||||||
|
физически разделил инстансы с одобрения владельца: food-market съехал в
|
||||||
|
собственный контейнер и том, а общий инстанс остался в compose-проекте
|
||||||
|
`shared-postgres` на старом томе (имя тома историческое — переименовывать
|
||||||
|
нельзя, в нём живые данные соседей). См. `docs/shared-postgres-followup-progress.md`.
|
||||||
|
|
||||||
|
**Правила:**
|
||||||
|
- Прод-бэкап, anonymize, schema-diff, миграции идут **только** через
|
||||||
|
`food-market-prod-postgres` (defaults скриптов именно такие).
|
||||||
|
- Контейнер `shared-postgres`, том `food-market-postgres-data`, порт `5434` —
|
||||||
|
**запрещённые** цели в наших compose/скриптах. Guards в `~/deploy-stage.sh`
|
||||||
|
и `~/quality-watchdog.sh` падают, если упомянутые паттерны всплывут в
|
||||||
|
шаблонах stage- или прод-compose в репе или на prod-vm.
|
||||||
|
- Нужен dump чужой базы — делает её владелец у себя, не из food-market.
|
||||||
|
- `deploy/shared-postgres/docker-compose.yml` в репе — это **документация**,
|
||||||
|
не исполняемый шаблон; наш `prod-deploy.sh` его не трогает.
|
||||||
|
|
||||||
## Бэкап и восстановление
|
## Бэкап и восстановление
|
||||||
|
|
||||||
### Расписание
|
### Расписание
|
||||||
|
|
@ -97,12 +128,20 @@ systemd-таймер `food-market-backup.timer` (см. `deploy/`) запуска
|
||||||
если сервер был выключен).
|
если сервер был выключен).
|
||||||
|
|
||||||
Скрипт `food-market-backup.sh`:
|
Скрипт `food-market-backup.sh`:
|
||||||
- `pg_dump -Fc` из контейнера `food-market-postgres` → `db-<TS>.dump`.
|
- `pg_dump -Fc` из контейнера `food-market-prod-postgres` → `db-<TS>.dump`.
|
||||||
- `tar czf` каталога `/opt/food-market-data/uploads` → `uploads-<TS>.tgz`.
|
- `tar czf` каталога `/opt/food-market-data/uploads` → `uploads-<TS>.tgz`.
|
||||||
- Удаляет файлы старше 30 дней (`FM_BACKUP_RETENTION_DAYS`).
|
- Удаляет файлы старше 30 дней (`FM_BACKUP_RETENTION_DAYS`).
|
||||||
|
|
||||||
Папка: `/opt/food-market-data/backups/`.
|
Папка: `/opt/food-market-data/backups/`.
|
||||||
|
|
||||||
|
> Контейнер прод-БД — `food-market-prod-postgres` (порт `127.0.0.1:5437`, том
|
||||||
|
> `food-market-prod-postgres-data`) с 2026-10-05. Соседний на той же машине
|
||||||
|
> `shared-postgres` (порт 5434, том `food-market-postgres-data` *external*) —
|
||||||
|
> **не наш**, в нём чужие боевые базы sklad/purchase/calcman/calcman\_staging/
|
||||||
|
> makesales. Любые `docker exec`/`pg_dump`/`pg_restore` в `shared-postgres` из
|
||||||
|
> наших скриптов запрещены, guards бьют. См. раздел «Postgres на prod-vm»
|
||||||
|
> ниже и `docs/shared-postgres-followup-progress.md`.
|
||||||
|
|
||||||
### Ручной бэкап
|
### Ручной бэкап
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -111,7 +150,7 @@ ssh nns@192.168.1.190 'sudo /opt/food-market/deploy/food-market-backup.sh'
|
||||||
|
|
||||||
Или из репо разработчика:
|
Или из репо разработчика:
|
||||||
```bash
|
```bash
|
||||||
deploy/backup.sh --remote 192.168.1.190:5434 # PG в Docker exposed на 5434
|
deploy/backup.sh --remote 192.168.1.190:5437 # прод-PG в Docker, exposed на 5437
|
||||||
```
|
```
|
||||||
|
|
||||||
### Recovery drill (RTO ≈ 25 секунд на сегодняшних данных)
|
### Recovery drill (RTO ≈ 25 секунд на сегодняшних данных)
|
||||||
|
|
@ -131,9 +170,9 @@ Sprint 15 — verified восстановление stage'а в свежий PG-
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Снять бэкап со stage'а
|
# 1. Снять бэкап со stage'а
|
||||||
ssh nns@192.168.1.190 'docker exec food-market-stage-postgres-1 \
|
ssh nns@192.168.1.190 'docker exec food-market-stage-postgres \
|
||||||
pg_dump -U food_market -d food_market -Fc -f /tmp/drill.dump'
|
pg_dump -U food_market -d food_market -Fc -f /tmp/drill.dump'
|
||||||
ssh nns@192.168.1.190 'docker cp food-market-stage-postgres-1:/tmp/drill.dump /tmp/drill.dump'
|
ssh nns@192.168.1.190 'docker cp food-market-stage-postgres:/tmp/drill.dump /tmp/drill.dump'
|
||||||
scp nns@192.168.1.190:/tmp/drill.dump /tmp/drill.dump
|
scp nns@192.168.1.190:/tmp/drill.dump /tmp/drill.dump
|
||||||
|
|
||||||
# 2. Чистый PG
|
# 2. Чистый PG
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,21 @@
|
||||||
|
|
||||||
| Что | Как | Файл |
|
| Что | Как | Файл |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| База данных | `pg_dump -Fc` из контейнера `food-market-postgres` | `db-<TS>.dump` (custom-format) |
|
| База данных | `pg_dump -Fc` из контейнера `food-market-prod-postgres` | `db-<TS>.dump` (custom-format) |
|
||||||
| Загруженные файлы (картинки товаров) | `tar czf` каталога uploads | `uploads-<TS>.tgz` |
|
| Загруженные файлы (картинки товаров) | `tar czf` каталога uploads | `uploads-<TS>.tgz` |
|
||||||
|
|
||||||
Папка назначения по умолчанию — `/opt/food-market-data/backups`. Хранение —
|
Папка назначения по умолчанию — `/opt/food-market-data/backups`. Хранение —
|
||||||
30 дней (`FM_BACKUP_RETENTION_DAYS`), старые удаляются ротацией. Конфиг —
|
30 дней (`FM_BACKUP_RETENTION_DAYS`), старые удаляются ротацией. Конфиг —
|
||||||
переменными `FM_*` (см. шапку `food-market-backup.sh`).
|
переменными `FM_*` (см. шапку `food-market-backup.sh`).
|
||||||
|
|
||||||
|
> **Контейнер прод-БД** — `food-market-prod-postgres` (с 2026-10-05, порт
|
||||||
|
> `127.0.0.1:5437`, том `food-market-prod-postgres-data`). Соседний контейнер
|
||||||
|
> `shared-postgres` (другой compose-проект, порт 5434) обслуживает чужие
|
||||||
|
> боевые базы соседних систем и food-market не принадлежит. Все `pg_dump`,
|
||||||
|
> `pg_restore`, `docker exec` в наших скриптах — только в
|
||||||
|
> `food-market-prod-postgres`. См. `docs/shared-postgres-followup-progress.md`
|
||||||
|
> и раздел «Postgres на prod-vm» в `docs/RUNBOOK.md`.
|
||||||
|
|
||||||
## Установка таймера на сервере (деплой-шаг)
|
## Установка таймера на сервере (деплой-шаг)
|
||||||
|
|
||||||
Предполагается, что репозиторий выложен в `/opt/food-market` (иначе скорректировать
|
Предполагается, что репозиторий выложен в `/opt/food-market` (иначе скорректировать
|
||||||
|
|
@ -59,17 +67,17 @@ docker compose stop api web
|
||||||
DUMP=/opt/food-market-data/backups/db-YYYYMMDD-HHMMSS.dump
|
DUMP=/opt/food-market-data/backups/db-YYYYMMDD-HHMMSS.dump
|
||||||
|
|
||||||
# Скопировать дамп внутрь контейнера БД
|
# Скопировать дамп внутрь контейнера БД
|
||||||
docker cp "$DUMP" food-market-postgres:/tmp/restore.dump
|
docker cp "$DUMP" food-market-prod-postgres:/tmp/restore.dump
|
||||||
|
|
||||||
# Вариант A — восстановить в чистую БД (рекомендуется):
|
# Вариант A — восстановить в чистую БД (рекомендуется):
|
||||||
docker exec food-market-postgres psql -U food_market -d postgres -c \
|
docker exec food-market-prod-postgres psql -U food_market -d postgres -c \
|
||||||
"DROP DATABASE IF EXISTS food_market WITH (FORCE); CREATE DATABASE food_market OWNER food_market;"
|
"DROP DATABASE IF EXISTS food_market WITH (FORCE); CREATE DATABASE food_market OWNER food_market;"
|
||||||
docker exec food-market-postgres pg_restore -U food_market -d food_market --no-owner /tmp/restore.dump
|
docker exec food-market-prod-postgres pg_restore -U food_market -d food_market --no-owner /tmp/restore.dump
|
||||||
|
|
||||||
# Вариант B — в существующую БД, заменив объекты (без пересоздания БД):
|
# Вариант B — в существующую БД, заменив объекты (без пересоздания БД):
|
||||||
# docker exec food-market-postgres pg_restore -U food_market -d food_market --clean --if-exists --no-owner /tmp/restore.dump
|
# docker exec food-market-prod-postgres pg_restore -U food_market -d food_market --clean --if-exists --no-owner /tmp/restore.dump
|
||||||
|
|
||||||
docker exec food-market-postgres rm -f /tmp/restore.dump
|
docker exec food-market-prod-postgres rm -f /tmp/restore.dump
|
||||||
docker compose start api web
|
docker compose start api web
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -92,9 +100,9 @@ sudo tar xzf "$TGZ" -C /opt/food-market-data/
|
||||||
## Проверка дампа без восстановления
|
## Проверка дампа без восстановления
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker cp <dump> food-market-postgres:/tmp/v.dump
|
docker cp <dump> food-market-prod-postgres:/tmp/v.dump
|
||||||
docker exec food-market-postgres pg_restore --list /tmp/v.dump | head # TOC валидного архива
|
docker exec food-market-prod-postgres pg_restore --list /tmp/v.dump | head # TOC валидного архива
|
||||||
docker exec food-market-postgres rm -f /tmp/v.dump
|
docker exec food-market-prod-postgres rm -f /tmp/v.dump
|
||||||
```
|
```
|
||||||
|
|
||||||
Скрипт и формат проверены локально (2026-05-27): дамп `PGDMP`, custom-format,
|
Скрипт и формат проверены локально (2026-05-27): дамп `PGDMP`, custom-format,
|
||||||
|
|
|
||||||
24
docs/shared-postgres-followup-progress.md
Normal file
24
docs/shared-postgres-followup-progress.md
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
# shared-postgres follow-up: репозиторий ↔ новая раскладка postgres прода
|
||||||
|
|
||||||
|
**Задача.** 2026-10-05 координатор физически разделил два инстанса postgres на prod-vm:
|
||||||
|
|
||||||
|
- `shared-postgres` (`~/shared-postgres/docker-compose.yml`, контейнер `shared-postgres`, порт `127.0.0.1:5434`, том `food-market-postgres-data` *external*). Внутри — ЧУЖИЕ боевые базы: `sklad`, `purchase`, `calcman`, `calcman_staging`, `makesales`, плюс мусорная старая `food_market` (повреждена, не восстанавливаем). Проект compose — `shared-postgres`, не наш, живёт отдельно.
|
||||||
|
- `food-market-prod-postgres` (`~/food-market/deploy/docker-compose.yml` на prod-vm, контейнер `food-market-prod-postgres`, порт `127.0.0.1:5437`, том `food-market-prod-postgres-data`). Это НОВЫЙ собственный postgres прода food-market. Пока не запущен — прод-API лежит.
|
||||||
|
|
||||||
|
Старый compose прода (project `deploy`, контейнер `food-market-postgres`, том `food-market-postgres-data` на тех же данных) **более не существует**. Простой при разделении — 12 секунд, соседи живы. Бэкап: `docker-compose.yml.bak-20261005` на prod-vm.
|
||||||
|
|
||||||
|
Теперь нужно догнать репозиторий (шаблоны, guards, скрипты, доки), чтобы следующий деплой из main не воскресил старую раскладку, а любой `docker exec` в `shared-postgres` из кода food-market был бы невозможен.
|
||||||
|
|
||||||
|
**Правила на будущее**
|
||||||
|
- Прод food-market использует `food-market-prod-postgres` / том `food-market-prod-postgres-data` / порт `127.0.0.1:5437`.
|
||||||
|
- `shared-postgres` **не принадлежит проекту food-market**. Его `container_name`, том и порт — запрещённые паттерны в наших compose/скриптах.
|
||||||
|
- Том `food-market-postgres-data` — исторический для `shared-postgres`, в food-market compose его быть не должно (чужие данные).
|
||||||
|
|
||||||
|
## Чеклист
|
||||||
|
|
||||||
|
- [x] 1. Шаблон репо `deploy/docker-compose.yml` приведён к прод-файлу (контейнер/том/порт прода). Добавлен `deploy/shared-postgres/docker-compose.yml` как документация соседнего compose-проекта (управляется отдельно).
|
||||||
|
- [x] 2. Guards расширены: `~/deploy-stage.sh` и `~/quality-watchdog.sh` (+их копии в репо, если есть) запрещают стенду `shared-postgres`, `food-market-prod-postgres`, `food-market-prod-postgres-data`, порты `5434`/`5437`; проду — том `food-market-postgres-data`.
|
||||||
|
- [x] 3. Скрипты и доки: `deploy/food-market-backup.sh`, `deploy/anonymize-prod.sh`, `deploy/db-schema-diff.sh`, `docs/RUNBOOK.md`, `docs/backup-restore.md` указывают на `food-market-prod-postgres` вместо старого `food-market-postgres`; RUNBOOK явно говорит «shared-postgres не наш».
|
||||||
|
- [x] 4. Проверка на prod-vm: `docker compose -f ~/food-market/deploy/docker-compose.yml config` и `docker compose ps -a` не упоминают `shared-postgres`; `grep` по репе — ни один скрипт не делает `docker exec` в `shared-postgres`.
|
||||||
|
|
||||||
|
Прод не запускается, `shared-postgres` и чужие базы не трогаются, `global.json` и gateway nginx вне скоупа.
|
||||||
Loading…
Reference in a new issue