Files
jellybit/docs/adr/ADR-2026-07-24-local-image-build.md
av 42d5b73a04 docs: перевод документации на канон av-dev
- Раскладка docs/ приведена к канону 2: заведены passport/architecture/
  database/security/review и research; docs/specs, drafts, backlog, review/
  и BRIEF.md разобраны и удалены, беклог переехал в docs/tasks (34 задачи,
  6 целей, слаги на английский).
- Нарративы specs удалены как дубли openspec-спек после поимённой сверки;
  остаток заведён задачами (редактор маппинга ревью, крайние случаи
  именования), отказ от сущности title промоутнут в ADR.
- Проектные копии агентов и скиллов ревью/пайплайна удалены в пользу
  плагинов av-dev-pm и av-dev-pipeline; в task gate добавлен шаг canon
  вместо er-schema.
2026-08-04 09:27:26 +03:00

5.6 KiB
Raw Permalink Blame History

Образ собирается локально и едет на сервер через docker save/load

  • Дата: 2026-07-24

Контекст

Заменяет ADR-2026-06-13-docker-deploy.

Docker как единица деплоя и распределение ответственности (Dockerfile — упаковка — живёт в jellybit; оркестрация — в umbar) остаются в силе. Пересматривается только как образ попадает на сервер.

Прежняя схема собирала статический бинарь на control-хосте, копировала на сервер бинарь + Dockerfile и делала docker build на месте. У этого два неудобства. Во-первых, на сервере остаётся шаг сборки: пусть дешёвый на Intel N150, но результат косвенно завязан на состояние сервера (его docker, его кэш), а не только на исходник. Во-вторых, схема одноразовая — она была вписана в playbook-jellybit.yml и не переиспользовалась. Появление второго такого же приложения (trackers) потребовало вынести доставку образа в общую ansible-роль app_image и заодно унифицировать контракт с приложением.

Рассмотренные варианты

  • Оставить сборку на сервере — прежнее решение. Держит на сервере шаг docker build и делает результат зависимым от состояния сервера; переиспользовать без копипасты плейбука неудобно.
  • Реестр (CI пушит образ, сервер тянет) — каноничнее, но в домашней лаборатории это лишний реестр и пайплайн ради одного узла. Отвергнуто по той же причине, что и в исходной ADR.
  • Собрать полный образ локально и доставить его docker save/load — выбрано: сборка целиком на control-хосте, сервер — только получатель, и реестр не нужен.

Решение

Доставку образа ведёт переиспользуемая роль app_image в umbar. Схема:

  • Контракт с приложением. Приложение реализует команду task image: получает BUILD_ID из окружения и собирает полный образ <app>:$BUILD_ID. Без BUILD_ID собирается <app>:dev — обратная совместимость для локальной работы. Приложение полностью владеет тем, как собирается его образ (Dockerfile — в репозитории приложения).
  • Сборка локальна. Роль генерит случайный BUILD_ID и гоняет с ним task image на control-хосте → образ <app>:$BUILD_ID. На сервере Go-тулчейн и docker build больше не нужны.
  • Тег = BUILD_ID. Deploy-тег — тот самый случайный BUILD_ID. Дедупликации по содержимому нет: тег нов на каждый прогон. Content-адресацию (тег из хеша слоёв/конфига образа) рассматривали и отвергли — на сценариях ручного нечастого деплоя выгода от неё не окупала сложности.
  • Доставка без реестра. docker save → copy tar → docker load. Каждый деплой везёт образ и пересоздаёт контейнер.
  • Уборка. Старые образы на сервере (тег каждого прошлого деплоя) подчищает docker image prune -af по крону (playbook-system.yml).

Последствия

  • + Сервер — только получатель образа: без Go-тулчейна и без шага docker build.
  • + Сборка целиком на control-хосте — воспроизводимее; состояние сервера на результат не влияет.
  • + Реестр по-прежнему не нужен — доставка дешёвая (save/load tar).
  • + Механизм общий (роль app_image), а не вписан в один плейбук — им же доставляется trackers.
  • - Дедупликации нет: тег = случайный BUILD_ID, поэтому каждый деплой везёт образ и пересоздаёт контейнер, даже если ничего не менялось. Для ручного нечастого деплоя это осознанный размен — простота роли важнее экономии одного рестарта.
  • - save/load везёт весь образ (базовый слой + бинарь), а не только бинарь, как в прежней схеме. Для distroless/static это единицы мегабайт — дёшево.