Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
170 lines
13 KiB
Markdown
170 lines
13 KiB
Markdown
# Окружение разработки АРМ КА (`docs/dev/`)
|
||
|
||
Локальная инфраструктура workspace одной командой: PostgreSQL 16, NATS 2.10 без JetStream и MinIO с бакетом `arm-ka`.
|
||
|
||
**Статус (фаза 1):** в compose сейчас только инфраструктура (`postgres`, `nats`, `minio`, `minio-init`). Профиль
|
||
`services` (контейнеры `arm-core`, `tabular-parser`, `scan-gateway`, `scan-emulator`) **планируется** — добавляется позже
|
||
(задача 5.3), здесь не описан. До этого сервисы запускаются из venv против этой инфраструктуры (см. ниже).
|
||
|
||
## Предварительные требования
|
||
|
||
- Docker и compose v2 (проверено на docker 28 / compose 2.34).
|
||
- `uv` и Python 3.11 — для запуска сервисов из venv (версия Python — как на платформе).
|
||
- Свободные порты хоста (по умолчанию доступны только с `127.0.0.1`, см. `BIND_ADDR`): 5432 (PostgreSQL), 4222 и 8222 (NATS и его мониторинг), 9000 и 9001 (MinIO API и консоль).
|
||
Занятые порты меняются в `.env` (см. «Типичные проблемы»).
|
||
|
||
## Запуск инфраструктуры
|
||
|
||
Команды — из каталога `docs/dev/`:
|
||
|
||
```bash
|
||
cp .env.example .env # .env в git не попадает
|
||
docker compose up -d # вернётся сразу; healthy — примерно через 6 с
|
||
```
|
||
|
||
Ожидание готовности (для скриптов и `Makefile`):
|
||
|
||
```bash
|
||
docker compose up -d && docker compose up -d --wait postgres nats minio
|
||
```
|
||
|
||
Голый `docker compose up -d --wait` **возвращает код 1**: одноразовый `minio-init` (создаёт бакет и завершается с
|
||
кодом 0) compose 2.34 считает сбоем (`container arm-ka-minio-init-1 exited (0)`). Поэтому `--wait` нужно давать со
|
||
списком долгоживущих сервисов — как выше.
|
||
|
||
Проверка:
|
||
|
||
```bash
|
||
docker compose ps # postgres, nats, minio — Up (healthy); minio-init — Exited (0)
|
||
docker compose exec postgres sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "select version()"'
|
||
curl -s localhost:8222/healthz # {"status":"ok"}
|
||
curl -s localhost:8222/varz | grep -A1 jetstream # "jetstream": {} — JetStream не включён
|
||
docker compose run --rm --entrypoint sh minio-init -c 'mc alias set local http://minio:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null && mc ls local'
|
||
# [...] 0B arm-ka/
|
||
```
|
||
|
||
Консоль MinIO — <http://localhost:9001> (по умолчанию `minioadmin` / `minioadmin`); S3 API — `localhost:9000`.
|
||
Схема БД (`dkb`) создаётся миграциями `arm-core`, не compose.
|
||
|
||
## Переменные `.env`
|
||
|
||
Файл читают `docker compose` (из этого каталога) и, вторым блоком, сервисы при запуске из venv. Значения по умолчанию —
|
||
только для dev.
|
||
|
||
Блок compose:
|
||
|
||
| Переменная | По умолчанию | Для чего |
|
||
|---|---|---|
|
||
| `BIND_ADDR` | `127.0.0.1` | адрес привязки всех портов хоста; `0.0.0.0` — доступ с других машин (небезопасно, см. «Примечания») |
|
||
| `POSTGRES_DB` | `armka` | имя БД |
|
||
| `POSTGRES_USER` | `armka` | пользователь БД |
|
||
| `POSTGRES_PASSWORD` | `armka` | пароль БД |
|
||
| `POSTGRES_PORT` | `5432` | порт PostgreSQL на хосте |
|
||
| `NATS_PORT` | `4222` | клиентский порт NATS на хосте |
|
||
| `NATS_MONITOR_PORT` | `8222` | порт мониторинга NATS (`/varz`, `/healthz`) |
|
||
| `MINIO_ROOT_USER` | `minioadmin` | администратор MinIO |
|
||
| `MINIO_ROOT_PASSWORD` | `minioadmin` | пароль администратора MinIO |
|
||
| `MINIO_API_PORT` | `9000` | порт S3 API на хосте |
|
||
| `MINIO_CONSOLE_PORT` | `9001` | порт консоли MinIO на хосте |
|
||
| `MINIO_BUCKET` | `arm-ka` | единственный бакет, создаётся `minio-init` |
|
||
|
||
Блок сервисов (запуск из venv против compose по `localhost`, формат шаблона команды):
|
||
|
||
| Переменная | По умолчанию | Для чего |
|
||
|---|---|---|
|
||
| `DEBUG` | `true` | dev-режим: пакеты `raisa_*` импортируются условно |
|
||
| `OPENBAO__DATABASE__DATABASE_URL` | `postgresql+asyncpg://armka:armka@localhost:5432/armka` | подключение к PostgreSQL (asyncpg) |
|
||
| `OPENBAO__MINIO__MINIO_URL` | `localhost:9000` | адрес MinIO без схемы (`host:port`, так ждёт `miniopy-async`) |
|
||
| `OPENBAO__MINIO__MINIO_ADMIN_LOGIN` | `minioadmin` | логин MinIO |
|
||
| `OPENBAO__MINIO__MINIO_ADMIN_PASSWORD` | `minioadmin` | пароль MinIO |
|
||
| `OPENBAO__MINIO__MINIO_BUCKET` | `arm-ka` | бакет |
|
||
| `OPENBAO__NATS__NATS_URL` | `nats://localhost:4222` | адрес NATS |
|
||
| `OPENBAO__NATS__NATS_SEED` | пусто | nkey seed; пусто — подключение без nkeys |
|
||
| `OPENBAO__NATS__NATS_JWT` | пусто | JWT NATS; пусто — подключение без nkeys |
|
||
| `OPENBAO__SMB__SMB_HOST` | `localhost` | заглушка SMB (в Срезе 0 не используется); блок обязателен для `Settings` arm-core |
|
||
| `OPENBAO__SMB__SMB_PATH` | `share` | заглушка SMB |
|
||
| `OPENBAO__SMB__SMB_LOGIN` | `user` | заглушка SMB |
|
||
| `OPENBAO__SMB__SMB_PASSWORD` | `password` | заглушка SMB |
|
||
| `NATS_ENABLED` | `true` | включает подключение arm-core к NATS; без него `/healthcheck` показывает `nats=off` |
|
||
|
||
Два блока описывают одни и те же ресурсы: **при смене порта, пароля, пользователя или бакета меняйте обе части.**
|
||
|
||
## Сброс окружения
|
||
|
||
```bash
|
||
docker compose down # останавливает контейнеры; тома postgres-data и minio-data сохраняются
|
||
docker compose down -v # полный сброс: удаляет тома postgres-data и minio-data (БД и бакет — с нуля)
|
||
```
|
||
|
||
Имя проекта compose фиксировано (`name: arm-ka`), поэтому тома общие для любого worktree (`.wt/<срез>/docs/dev`):
|
||
сброс из одного worktree затрагивает все.
|
||
|
||
## Запуск сервисов из venv без Nexus (черновик)
|
||
|
||
> Черновик: будет дописан и проверен вручную в задаче 5.4 (сквозная проверка). `make venv` и `make test-integration`
|
||
> в `tabular-parser` и `scan-gateway` будут доступны после задач этих сервисов; сейчас они есть в `arm-core`.
|
||
|
||
Пакеты `raisa_*` из Nexus банка вне банка недоступны (D-10). Поэтому `make venv` ставит `requirements.txt` без строк
|
||
`raisa_*` (фильтр `grep -v '^raisa_'`), код импортирует `raisa_*` условно (при `DEBUG=true`), а npm-пакеты `raisa-*`
|
||
в `web/package.json` вынесены в `optionalDependencies`.
|
||
|
||
Шаги для сервиса (пути — относительно каталога его репозитория; в workspace `docs/` лежит рядом, `../docs/dev/`):
|
||
|
||
```bash
|
||
# 1. поднять инфраструктуру (из docs/dev/, см. выше)
|
||
# 2. из корня репозитория сервиса:
|
||
cp ../docs/dev/.env.example api/.env
|
||
make venv # api/.venv: Python 3.11 + зависимости без raisa_*
|
||
cd api && .venv/bin/python run_server.py # сервис подключается к PostgreSQL/NATS/MinIO по localhost
|
||
# 3. в другом терминале:
|
||
curl -s localhost:<порт сервиса>/healthcheck
|
||
```
|
||
|
||
Порт сервиса задаётся его настройками; в профиле `services` по spec это 8000 (`arm-core`), 8001 (`tabular-parser`),
|
||
8002 (`scan-gateway`). Для `arm-core` в ответе `/healthcheck` ожидаются `version` и `nats = ok` — при `NATS_ENABLED=true`
|
||
(задан в `.env.example`; без него `nats = off`). Для `tabular-parser` и `scan-gateway` ожидаемые поля и переменные
|
||
зависят от их настроек — будет уточнено в задачах 5.x.
|
||
|
||
## Интеграционные тесты сервисов против compose (черновик)
|
||
|
||
> Черновик: уточняется после задач 3.x и 5.x.
|
||
|
||
Общий набор целей (`up`, `test`, `test-integration`, `lint`, `check`, `check-full`) есть во всех сервисных репозиториях
|
||
(`arm-core`, `tabular-parser`, `scan-gateway`); семантика, состав `check-full`, порядок перед PR и пропуск тестов без
|
||
`docs`/`fixtures` описаны в [`checks.md`](checks.md); эталон рецептов общих целей — [`Makefile.common`](Makefile.common). Кратко: `make check` — быстрые проверки без Docker, `make check-full` —
|
||
`check` + интеграционные тесты против этого compose + образ (для `arm-core` ещё сверка с DBML, миграции и `web`);
|
||
выполняется перед созданием PR.
|
||
|
||
Интеграционные тесты **требуют поднятой инфраструктуры**: сначала `docker compose up -d && docker compose up -d --wait
|
||
postgres nats minio`, затем `make test-integration` (или `make check-full`) в репозитории сервиса. Для `scan-gateway`
|
||
эмулятор ИС Сканирование поднимается в процессе интеграционного теста (отдельный контейнер появится вместе с профилем
|
||
`services`). Общее описание проверок — [`checks.md`](checks.md).
|
||
|
||
## Проверка контракта
|
||
|
||
Из корня репозитория `docs`: `python scripts/validate_contracts.py` — валидирует примеры в
|
||
[`contracts/examples/`](../contracts/examples/) тремя схемами из [`contracts/`](../contracts/) (3 схемы, 8 примеров;
|
||
нужен `jsonschema`). Или `make venv && make check` (ещё `openspec validate`), см. [`checks.md`](checks.md).
|
||
|
||
## Примечания
|
||
|
||
- **Образы MinIO неофициальные.** Официальные `minio/minio` и `minio/mc` недоступны (Docker Hub — denied, на quay.io нет
|
||
нужных тегов), поэтому в compose стоят `alpine/minio:RELEASE.2025-10-15T17-29-55Z` и
|
||
`bitnamilegacy/minio-client:2025.7.21`, а сервис `minio` запущен с `user: "0:0"` (иначе образ не пишет в свежий том) —
|
||
только для dev. Решения R-5/R-6: [`design.md`](../openspec/changes/slice-0-skeleton/design.md), раздел
|
||
«Decisions made without discussion», решения №16–17. Замена на официальные образы — две строки `image:` в
|
||
`docker-compose.yml` (и удаление `user: "0:0"`).
|
||
- **Безопасность.** По умолчанию порты публикуются только на `127.0.0.1` (`BIND_ADDR`), снаружи машины они недоступны.
|
||
Чтобы открыть их для других машин, задайте в `.env` `BIND_ADDR=0.0.0.0` — но пароли по умолчанию (`armka`,
|
||
`minioadmin`) годятся только для dev, поэтому сначала смените их (в обоих блоках `.env`) и не делайте этого в
|
||
недоверенной сети.
|
||
|
||
## Типичные проблемы
|
||
|
||
- **Порт занят** (`address already in use`): измените `*_PORT` в `.env` и одновременно соответствующий порт в
|
||
`OPENBAO__*` (`DATABASE_URL`, `MINIO_URL`, `NATS_URL`); перезапустите `docker compose up -d`.
|
||
- **`minio-init` завис или завершился с ошибкой:** `docker compose logs minio-init`; чаще всего `minio` не стал healthy —
|
||
`docker compose logs minio`. Повторный `docker compose up -d` идемпотентен.
|
||
- **Остаточные тома от прошлых запусков** (старый пароль БД, бакет не тот): `docker compose down -v` и запуск заново.
|
||
- **`up -d --wait` возвращает код 1:** см. раздел «Запуск инфраструктуры» — указывайте сервисы явно.
|