Docker удобен, пока вы работаете на своей машине. В CI и на серверах сборки демон становится проблемой: он требует root, хранит состояние между запусками и добавляет слой, которого нет в продакшене. Buildah и Skopeo решают ту же задачу иначе — собирают и переносят OCI-образы без демона, в обычном пользовательском окружении. Разберём практическую работу с ними.
Роли в экосистеме
Buildah отвечает за сборку: он умеет выполнять Dockerfile, запускать команды в контейнере, монтировать файловую систему и коммитить результат в образ. Skopeo работает с готовыми образами: инспектирует манифесты, копирует между реестрами, синхронизирует теги и удаляет их. Обе утилиты используют общие библиотеки containers/image и containers/storage, поэтому понимают друг друга без экспорта в tar-архив.
Вместе с Podman они образуют стек, где нет постоянного фонового процесса: каждая команда — отдельный процесс, который завершается вместе с работой. Это упрощает аудит и позволяет запускать сборку в контейнере без привилегий.
Установка
sudo apt install buildah skopeo
sudo dnf install buildah skopeo
buildah --version && skopeo --version
podman info --format '{{.Host.Security.Rootless}}'
Пакеты есть в Debian, Ubuntu, Fedora, RHEL и openSUSE. Версии в дистрибутивах отстают от upstream, но для сборки это редко критично. Для самой свежей связки используйте репозиторий проекта или статически собранные бинарники.
Rootless: подготовка
Сборка без root опирается на user namespaces. Убедитесь, что в /etc/subuid и /etc/subgid есть диапазон для вашего пользователя.
grep "$USER" /etc/subuid /etc/subgid
buildah unshare id
buildah info --format '{{.Store.GraphDriverName}}'
Если overlay в rootless-режиме недоступен, поставьте fuse-overlayfs и укажите драйвер в ~/.config/containers/storage.conf. Без этого Buildah свалится на монтировании слоёв.
[storage]
driver = "overlay"
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"
Альтернатива — драйвер vfs: он работает везде, но занимает больше места и медленнее. Для одноразовых CI-раннеров это приемлемая цена, для рабочей машины — нет.
Сборка из Dockerfile
buildah build -t registry.example.com/app:1.0 .
buildah build --layers --format oci -t app:test .
buildah images
buildah inspect app:test | head -40
Команда buildah build заменила устаревший buildah bud. Флаг --layers включает кэширование слоёв: без него каждая сборка выполняется целиком. --format oci даёт образ в формате OCI, --format docker — в классическом; для Kubernetes чаще берут OCI.
Полезные флаги: --build-arg для параметров, --platform linux/amd64 для кросс-сборки, --no-cache для чистой проверки, --secret для передачи токенов без попадания в слои. Секреты через ARG — распространённая ошибка: они остаются в истории образа.
Для многоступенчатой сборки Buildah ведёт себя как Docker: стадии описываются через FROM ... AS builder, а в финальный образ попадает только результат. Требование к базовому образу то же — он должен быть доступен в реестре или локальном хранилище. Практический выигрыш от --layers появляется, когда зависимости ставятся до копирования исходников: неизменный слой переиспользуется, и сборка сокращается с минут до секунд.
Не забывайте про .containerignore: без него в контекст попадут .git, виртуальные окружения и тестовые данные. Это замедляет передачу контекста и увеличивает итоговый образ, если в Dockerfile есть COPY . ..
Сборка без Dockerfile
Иногда проще описать шаги скриптом — особенно когда нужна тонкая работа с файлами или отладка на полпути.
ctr=$(buildah from alpine:3.21)
buildah run "$ctr" -- apk add --no-cache curl
buildah copy "$ctr" ./app /usr/local/bin/app
buildah config --entrypoint '["/usr/local/bin/app"]' "$ctr"
buildah commit "$ctr" app:script
Контейнер существует, пока вы его не удалите: buildah containers покажет список, buildah rm --all очистит. Это удобно для отладки — можно зайти внутрь через buildah run "$ctr" -- sh и посмотреть, что получилось. Не забудьте про --pull-never, если базовый образ должен браться только из локального кэша.
Skopeo: образы без скачивания
skopeo inspect docker://docker.io/library/nginx:latest
skopeo list-tags docker://registry.example.com/app
skopeo copy docker://docker.io/library/nginx:latest oci:./nginx-oci:latest
skopeo sync --src docker --dest dir registry.example.com/app ./mirror
inspect показывает метки, слои и архитектуру, не занимая место в локальном хранилище. copy переносит образ между реестрами напрямую: трафик идёт от источника к приёмнику, не оседая на вашей машине. sync полезен для зеркал — он сохраняет структуру тегов и умеет работать по списку.
Для мультиархитектурных образов добавьте --all: Skopeo перенесёт индекс целиком, а не одну платформу. Если нужно проверить конфигурацию без загрузки слоёв, используйте skopeo inspect --config. При копировании в dir получается обычный набор файлов, который удобно класть на файловый сервер или отдавать как офлайн-зеркало внутри закрытого контура.
Публикация и подпись
buildah login registry.example.com
buildah push app:1.0 docker://registry.example.com/app:1.0
skopeo copy --all docker://registry.example.com/app:1.0 docker://backup.example.com/app:1.0
skopeo delete docker://registry.example.com/app:old
Учётные данные хранятся в ${XDG_RUNTIME_DIR}/containers/auth.json и подхватываются всеми утилитами стека. Для проверки целостности используйте подпись: skopeo copy --sign-by и политику policy.json. В 2026 году стандартом де-факто остаётся cosign с ключами в KMS, и Skopeo умеет работать с ним через плагины.
Диагностика
buildah info— драйвер хранилища, корень, доступные архитектуры.buildah imagesиbuildah containers— что уже создано.- Ошибка
unauthorized— проверьтеauth.jsonи права токена. no space left on device— очиститеbuildah rm --allиbuildah rmi --prune.- Медленная сборка — включите
--layersи вынесите редко меняющиеся шаги в начало Dockerfile. - Конфликт UID — проверьте
/etc/subuid, диапазоны не должны пересекаться между пользователями. - Образ не запускается под Podman — сверьте
ENTRYPOINTи архитектуру черезskopeo inspect.
Чек-лист для CI
- Сборка идёт от непривилегированного пользователя.
- Теги содержат хеш коммита, а не только
latest. - Секреты передаются через
--secret, а неARG. - Образ сканируется на уязвимости до публикации.
- Кэш слоёв сохраняется между запусками пайплайна.
- В Dockerfile закреплены версии базовых образов и пакетов.
Итог
Buildah и Skopeo снимают главное неудобство Docker в автоматизации — зависимость от демона и root-прав. Buildah собирает образы из Dockerfile или скрипта, Skopeo переносит и инспектирует их без лишних загрузок. Связка хорошо ложится в CI, где важны воспроизводимость, скорость и минимум привилегий.