# Docker-образы EvoFirewall ## CI (Gitea Actions) Сборка образов — **`docker buildx bake`** ([docker-bake.hcl](docker-bake.hcl)), не отдельные `docker build`. **Publish:** push в `main` после quality gates — workflow [CD](../../.gitea/workflows/cd.yaml) job **publish**: semantic-release + зеркало base-образов + bake с `VERSION` из релиза. Bake читает переменные из **окружения** (`REGISTRY`, `IMAGE_TAG`, `CACHE_REF_NODE`, `BASE_NODE`). Скрипт [write-bake-override.sh](write-bake-override.sh) — опциональный helper для локальной отладки. BuildKit кэширует pnpm store через `RUN --mount=type=cache`. На CI mounts живут, пока named builder `evofw` не удаляют (`cleanup: false`). ### Слои и runtime | Образ | Runtime base | Заметка | |-------|----------------|---------| | `evofw`, `evofirewall` | `node:22-alpine` | один процесс: API + SPA + SQLite; `better-sqlite3` собирается в alpine в dependency stage | `python3` / `make` / `g++` только в build stages. Независимые `api-build` / `web-build` ветви используют общий `deps`; runtime получает только production API deploy и SPA dist. Context режется корневым [.dockerignore](../../.dockerignore). Теги `evofw` и `evofirewall` — один и тот же образ (`evofirewall` — drop-in для старого compose). ### Кэш registry - `git.shx.one//evofw-buildcache:node-buildcache` — **запись** только из финального `evofw` target (`mode=max` включает обе build branches). PR импортирует cache без записи. - `git.shx.one//evofw-buildcache:base-node-22-alpine-` — зеркало FROM с Docker Hub. Только `linux/amd64`; upstream digest проверяется перед выбором зеркала, bake получает mirror reference по digest. Ошибка resolution/copy блокирует CD. `pull = false` в bake: не перекачивать FROM, если слой уже в builder. Не запускайте `docker system prune -a` на runner. Параллельный `cache-to` в один ref ломает manifest (`content descriptor … not found`). Если CI падает на «not found» после смены схемы кэша — один раз удалите теги `evofw-buildcache:*` в registry и пересоберите. Runtime smoke, backup/restore, baseline и оставшиеся release gates: [runtime-validation.md](../../docs/runtime-validation.md). ## Локальная сборка Из корня репозитория: ```bash cd deploy/docker export REGISTRY=git.shx.one/ export IMAGE_TAG=latest export SHORT_SHA=$(git rev-parse --short HEAD) export VERSION=dev export BUILD_TIME= docker buildx bake --allow=fs.read=../.. -f docker-bake.hcl default ``` Проверка манифеста без сборки: ```bash docker buildx bake --allow=fs.read=../.. -f docker-bake.hcl --print default ``` В `docker-bake.hcl`: `context = "../.."` резолвится **от cwd** (каталог `deploy/docker/`). `dockerfile` — путь от этого context (корень репо). Из корня репо не вызывать bake с `-f deploy/docker/docker-bake.hcl`: получится `lstat ../../deploy`. Можно задать `BUILDX_BAKE_FILE_RELATIVE_PATHS=1`.