--- work_item: ORCH-062 stage: architecture author_agent: architect status: proposed created_at: 2026-06-09 model_used: claude-opus-4-8 --- # 07 — Инфра-требования: ORCH-062 — авто-prune docker build cache на mva154 Work Item: **ORCH-062** · Repo: **orchestrator** · Стадия: architecture > Решение: **Вариант A** (фоновый демон приложения, `docker builder prune` на хосте через ssh) — > см. `06-adr/ADR-001-build-cache-pruner.md`. Этот файл фиксирует host-prerequisites выбранного > пути и задокументированный ручной fallback (Вариант C, host-cron). ## I-1. Топология / окружения - Без изменений топологии: **новый внутренний фоновый daemon-поток** в существующем прод-контейнере `orchestrator` (8500), наравне с `reconciler`/`job_reaper`/`disk_watchdog`. Новых контейнеров, портов, сетей, томов — **нет**. - Уборка исполняется **на хосте mva154** (host docker daemon — там физически живёт build cache) через уже существующий ssh-канал `deploy_ssh_user@deploy_ssh_host` (по образцу `image_freshness`/`self_deploy` Phase B). В контейнере `docker` CLI **нет** (`Dockerfile:11` — только `openssh-client git curl`), поэтому raw-вызов CLI в контейнере невозможен — только ssh на хост. ## I-2. Переменные окружения / секреты Новые env (дефолты безопасны; полная карта — `docs/operations/INFRA.md`; канон — `.env.example`): | env | Дефолт | Назначение | |-----|--------|------------| | `ORCH_BUILD_CACHE_PRUNE_ENABLED` | `true` | kill-switch; `false` → демон не стартует, 1:1 как до задачи | | `ORCH_BUILD_CACHE_PRUNE_INTERVAL_S` | `21600` (6ч) | период тика, сек (валидация >0, иначе → дефолт) | | `ORCH_BUILD_CACHE_PRUNE_UNTIL` | `24h` | возраст удержания тёплого кэша (`--filter until=`); валидация `^\d+[smhdw]?$`, иначе → `24h` | | `ORCH_BUILD_CACHE_PRUNE_ALL` | `false` | добавить `-a` (только в паре с `until`) | | `ORCH_BUILD_CACHE_PRUNE_TIMEOUT_S` | `120` | таймаут ssh-команды, сек | | `ORCH_BUILD_CACHE_PRUNE_NOTIFY_MIN_GB` | `0` | Telegram при освобождении ≥ N ГБ; `0` → тихо | - Переиспользуются существующие `ORCH_DEPLOY_SSH_USER` (дефолт `slin`) / `ORCH_DEPLOY_SSH_HOST` как ssh-таргет. **Пустой `ORCH_DEPLOY_SSH_HOST` → тик no-op** (фича не активна вне self-host). - Секретов не добавляет. ssh-ключи уже проброшены ro (`~/.orchestrator-ssh → /home/slin/.ssh`, ORCH-040); в git не коммитятся. ## I-3. Деплой / рестарт - **Рестарт docker daemon — НЕ требуется** (ключевое отличие от отклонённого Варианта B). Уборка — это `docker builder prune` (BuildKit GC), без правки `daemon.json`. - **Рестарт прод-контейнера ради уборки — категорически НЕ требуется и запрещён** (self-hosting групповой риск). Сам код демона активируется штатным конвейерным деплоем оркестратора (staging 8501 → Confirm Deploy → prod), не отдельной операцией. - Host-prerequisites выбранного пути A (процедура Owner, в git не коммитятся — как P-1…P-4 в INFRA.md): 1. На хосте установлен `docker` и пользователь `slin` — в группе `docker` (уже выполняется: деплой-хук запускает `docker compose` на хосте). 2. ssh с контейнера на хост под `slin` работает без пароля (уже настроено для Phase B деплоя). Иные действия Owner не требуются — фича включена дефолтом и активна при наличии ssh-таргета. ### Ручной fallback (Вариант C, host-cron) — если ssh-канал недоступен Если по какой-то причине ssh-канал на хост закрыт, эквивалентную защиту можно временно обеспечить host-cron на mva154 (процедура Owner, off-git): ```cron # каждые 6 часов: удалить build cache старше 24ч (только build cache, не образы/контейнеры) 0 */6 * * * docker builder prune -f --filter until=24h >> /var/log/orch-build-cache-prune.log 2>&1 ``` Это fallback, не основной путь: cron не наблюдаем в `GET /queue` и не имеет config-kill-switch. ## I-4. CI/CD - `.gitea/workflows/` — **без изменений**. Добавляется юнит-тест `tests/test_build_cache_pruner.py` (путь A), исполняется существующим `pytest tests/ -q`; docker/ssh в тестах мокируются (как `image_freshness`-тесты не требуют реального docker).