16 KiB
Context
Согласован отдельный репозиторий deploy и команда ./deploy.sh <tag> по SSH.
Тег принадлежит комплекту, а не компоненту; соответствие пары хранится в
release.env. Решения приняты в обсуждении с владельцем и записаны в ADR 016
репозитория docs; эти артефакты готовят реализацию, не подтверждают её выполнение.
На сервере уже есть Compose project wealthledger, SQLite, постоянные ключи
и read-only mount certs/tbank-ca.pem через TBANK_CA_CERT_PATH. Внешний HTTPS
и Docker подготовлены. Образы публикуются в Nexus независимыми релизами.
containerized-application-delivery остаётся отдельным active change;
его runtime-контракт используется без редактирования или преждевременного archive.
Goals / Non-Goals
Goals: небольшой комплект с воспроизводимой парой образов, одним entrypoint, безопасным обновлением SQLite и понятным восстановлением существующего сервера.
Non-Goals: provisioning, CI/CD автодеплой, новый registry, Kubernetes, Ansible-инфраструктура, blue-green, замена БД, backup daemon, автоматическая ротация копий, собственная система миграций или управление HTTPS.
Decisions
Комплект и постоянные ресурсы
Минимальное содержимое deploy: compose.yaml, release.env, .env.example,
deploy.sh, README и одна исполняемая проверка сценариев. Compose использует
готовые frontend/backend images, migration запускается из backend image.
Production-комплект самодостаточен и не требует соседних checkout.
Существующие root Compose-файлы для development не удаляются этим change.
На сервере checkout располагается отдельно от data/, certs/, backups/
и защищённого server env. Например, checkout — /opt/wealthledger/deploy,
остальное — соседние пути в /opt/wealthledger. Существующий data path
не переименовывается; пути bind mounts абсолютные. Ключи не генерируются
повторно. Root filesystem остаётся read-only, процесс non-root, backend
не получает host port; сертификат доверия монтируется read-only без отключения TLS.
release.env содержит только полные versioned image references из Nexus;
latest исключён. Server env хранит настройки и секреты, но не выбирает пару.
Переменные окружения вызывающего shell не должны переопределять выбранные
images или Compose project. Env-файлы обрабатываются Compose как данные,
не выполняются shell через source. Полный config с секретами не печатается.
Исполнение выбранной версии
Entrypoint получает тег только из настроенного доверенного origin, разрешает
его в commit и использует содержимое этого commit для всей операции, включая
версию deploy-логики. Полученный ранее тег не перезаписывается при расхождении.
Работа идёт из временного snapshot выбранного commit; запущенный скрипт и
операторские изменения checkout не перезаписываются переключением ветки.
Compose file, env files и project wealthledger задаются явно: временная
директория не должна создать второй project или изменить пути данных.
До остановки выполняются проверки входов, ресурсов, конфигурации и загрузка
образов. Поддерживаемый target — один Linux Docker host; Git, Bash и flock
входят в перечисленные README предпосылки. Архитектура опубликованных образов
должна соответствовать серверу; multi-platform поддержку этот change не добавляет.
Обновление, повтор и состояние
Один flock на установку исключает конкурирующие запуски. Не добавляется
сервис блокировок. Файл блокировки и минимальные служебные записи находятся
вне checkout, с ограниченными правами, без секретов.
Нужны только запись последнего успешного релиза и маркер незавершённого обновления: выбранный commit, фактические images, этап и расположение backup. Маркер сохраняется до первого изменения runtime; успешная запись атомарно обновляется только после готовности затронутых сервисов. При прерывании маркер остаётся для диагностики; новый запуск требует ручного разбора по README. Это не журнал всех deployments и не отдельная база состояний. При первом переходе предыдущая версия описывается фактической парой images: несуществующий тег прежнего комплекта не придумывается.
План изменений сверяет желаемые images и Compose service configuration с фактическими контейнерами. Для сравнения использовать native Compose service hash и Docker labels, если их соответствие подтверждено проверкой. Секреты не записываются в служебные файлы. Отсутствие достоверного baseline не разрешает frontend-only shortcut: первый переход с серверного Compose выполняется как полное обновление с backup. Успешная запись сама по себе не заменяет проверку фактически работающих контейнеров.
При обновлении API: stop backend → проверка отсутствия migration writer →
новый уникальный каталог backup → копия всего data directory, включая WAL/SHM →
одноразовая migration → backend readiness. Для существующей установки отсутствие
wealthledger.db — ошибка. Только явный первый запуск --init на пустом
каталоге без прежнего runtime допускает создание новой базы без backup.
Копия отмечается пригодной для восстановления только после успешного окончания
копирования; незавершённый каталог не выдаётся за готовый backup.
Неизменный frontend не пересоздаётся; обновление только frontend не запускает зависимости. При обновлении обоих компонентов новый frontend запускается после готовности backend. Healthchecks используются из готовых images через Compose; новый HTTP endpoint не нужен. Browser smoke через HTTPS остаётся отдельной проверкой выпуска: container health не доказывает login/refresh.
Backup failure и migration failure прекращают последовательность. При провале readiness backend останавливается. Провал frontend не останавливает исправный backend. Любая ошибка оставляет релиз неподтверждённым, текущую БД и backup неизменёнными процедурой восстановления; диагностика не выводит secrets.
Выпуск и инструкция
После публикации компонентов оператор меняет пару в release.env, проверяет
её на disposable установке и выпускает отдельный неизменяемый vX.Y.Z тег
deploy. Компонентные pipeline не связываются автоматическим publisher.
Первый комплект закрепляет реально доступные образы, не демонстрационные версии.
README описывает подготовку Docker/Git/registry/HTTPS, разрешения каталогов,
сохранение ключей, подключение действующего Compose project, install/update,
диагностику незавершённой операции, ручную очистку backups и recovery.
UI/UX Applicability and Package
Applicability and scope: N/A — браузерный интерфейс и его состояния
не меняются; оператор использует терминал и README. Макеты не нужны.
Delivery Map
| Area | Status | Architectural outcome or N/A reason |
|---|---|---|
| frontend | N/A |
Готовый image переиспользуется, UI и pipeline не меняются |
| backend | N/A |
Готовые runtime, healthcheck и migrations переиспользуются |
| specs | affected |
Контракт deployment-bundle и план его проверки |
| docs | affected |
ADR 016 и обновлённый эксплуатационный маршрут после реализации |
| deploy | affected |
Самодостаточный комплект, сценарии проверки и README |
| root | affected |
Только навигация README к production-комплекту; development Compose не меняется |
Уточнение старого шаблона: обязательные четыре области сохранены; добавлен
реальный repository owner deploy, явно выбранный пользователем, и root
для необходимой поправки workspace-навигации. В Tasks используются [deploy]
и [root], а не фиктивный [backend] или [workspace].
Это локальное расширение перечня owners для данного change; глобальная
переработка SDD schema и process specs в scope не входит. Native structural
validation не доказывает соответствие этому уточнению или semantic approval.
Solution Assessment
| Вариант | Fit, зрелость и безопасность | Стоимость и ограничения |
|---|---|---|
| Только Docker Compose | Зрелый runtime, зависимости, healthchecks и выбор images уже покрыты | Не выполняет stop/copy/migrate и не исключает две операторские операции |
| Bash + Git + Compose + flock | Native инструменты владеют загрузкой, запуском и блокировкой; shell связывает существующий безопасный порядок | Небольшой branching требует проверок ошибок и прерываний; подходит одному Linux host |
| Ansible | Зрелый механизм управления серверами, но backup/migration порядок всё равно надо определить | Добавляет control environment, inventory и роль при уже подготовленном одном сервере |
Выбран второй вариант. Чистого Compose недостаточно для согласованной копии при остановленной записи; отдельный provisioning stack не соответствует согласованному отсутствию управления серверной инфраструктурой. Новый package manager, framework или сторонняя runtime-зависимость не вводятся.
Risks / Trade-offs
- Краткий простой и единственный writer сохраняются; внешние процессы записи должны быть исключены оператором при подключении существующей установки.
- Локальный backup не спасает от потери диска; свободное место и ручная очистка остаются эксплуатационной обязанностью. Ошибка копирования блокирует миграции.
- Native hash может измениться между версиями Compose: сомнение приводит к полному безопасному обновлению, а не к пропуску backup.
- Прерванная migration требует разбора, а не слепого повторения команды. Ни служебный маркер, ни последний успешный тег не являются копией базы.
- Доверие к Git origin и неизменяемым Nexus release tags остаётся существующей границей поставки; собственная система подписей здесь не добавляется.
Migration Plan
Подготовить самодостаточный комплект и проверить безопасный lifecycle на disposable данных. Затем обновить docs, сохранив development-инструкцию. Для действующего сервера сохранить старые настройки и соответствие images, подключить существующие абсолютные пути и project, выполнить первый полный переход с backup. Старый способ запуска не выполнять параллельно.
Rollback Contract
| Field | Decision |
|---|---|
| Status | required |
| Trigger | Ошибка migration/readiness, прерывание либо выявленная регрессия |
| Actions | Остановить API при риске для данных; отдельно выбрать совместимый image либо explicit restore; незавершённый маркер снять только после проверки состояния |
| Data safety | Не восстанавливать БД автоматически; перед explicit restore сохранить текущий каталог, выбрать копию, подтвердить потерю новых записей и наличие прежнего ключа |
| Verification | На отдельной копии проверить целостность БД, совместимость схемы, auth/cards и расшифровку подключения; после восстановления повторить smoke через HTTPS |