Простейший distroless-образ
Начинать лучше с маленького образа, который запускает один бинарник. В flowforge такой образ
удобно делать в org/base, потому что там уже лежит базовая distroless-цепочка. Сам
DistrolessImage выбирается не по организации, а по секции distroless в info.yaml.
Реальный минимальный пример уже есть в репозитории: org/base/distroless-true. Он кладёт
в rootfs /bin/true из пакета coreutils и запускает его.
Каталог
org/base/distroless-true/
Dockerfile.template
altflow-test
info.yaml
info.yaml
---
is_versioned: false
binary_packages:
- coreutils
source_images:
- base/distroless-builder
- base/distroless-static
distroless:
from: "{{ registry }}{{ branch }}/distroless-static:latest"
builder:
reinstall_packages:
- coreutils
rootfs:
files:
- /bin/true
cmd:
- /bin/true
annotations:
org.opencontainers.image.revision: ""
org.opencontainers.image.source: ""
org.opencontainers.image.url: ""
org.opencontainers.image.version: ""
org.opencontainers.image.title: "distroless-true"
org.opencontainers.image.description: "True-command image for zero status returning"
org.opencontainers.image.licenses: GPLv2
org.opencontainers.image.vendor: "ALT Linux Team"
...
Разбор по смыслу:
is_versioned: false,binary_packagesиsource_images- общие поля спецификации. Их смысл описан в формате спецификаций. Дляdistroless-trueважная практическая связь такая:coreutilsотслеживается как пакет-зависимость, аbase/distroless-builderиbase/distroless-staticзадают порядок сборки.distroless.fromзадаёт финальныйFROMчерез функциюdistroless_from(). Если не указано иное, функция строит итоговый образ отscratch. В этом примере итоговый образ строится поверхdistroless-static, что указано явно.distroless.builder.reinstall_packagesперечисляет пакеты, которые надо поставить или переустановить в builder-стадии перед извлечением файлов. Здесь снова указанcoreutils, но смысл другой: это не проверка актуальности, а подготовка файла/bin/trueдля rootfs.distroless.rootfs.filesговоритdistroless-builder.py, какие конкретные файлы забрать из builder-стадии. Дляtrueдополнительные библиотеки искать не нужно.distroless.cmdзадаётCMDфинального образа.annotationsзадаёт OCI metadata. Это общее поле, но его удобно видеть рядом с примером.
coreutils повторяется намеренно. В binary_packages он описывает зависимость образа. В
distroless.builder.reinstall_packages он уже управляет сборкой: пакет должен быть установлен
в builder-стадии, иначе distroless-builder.py не сможет положить /bin/true в rootfs.
В минимальном примере это один и тот же пакет, но в более сложных образах список зависимостей
образа и список пакетов для подготовки rootfs могут отличаться.
Dockerfile.template
Минимальный шаблон обычно повторяет схему существующих distroless-образов:
FROM {{ registry }}{{ branch }}/distroless-builder:latest AS builder
WORKDIR /usr/src/distroless
{{ distroless_base_rootfs() }}
{{ distroless_reinstall() }}
{{ distroless_add() }}
FROM {{ distroless_from() }}
COPY --from=builder /rootfs/ /
{{ distroless_config() }}
LABEL org.opencontainers.image.title="distroless-true" \
org.opencontainers.image.description="True-command image for zero status returning" \
org.opencontainers.image.licenses="GPLv2" \
org.opencontainers.image.vendor="ALT Linux Team"
Шаблон короткий, потому что основная логика спрятана в helper'ах renderer'а DistrolessImage.
Строки читаются так:
- первый
FROMзапускает builder-стадию изdistroless-builder; WORKDIRвыбирает каталог, где лежитdistroless-builder.py;distroless_base_rootfs()распаковывает базовый rootfs в/basefs, чтобы потом не добавлять в новый слой файлы, которые уже есть в итоговом указанном вdistroless.fromобразе;distroless_reinstall()ставит или переустанавливает пакеты изdistroless.builder.reinstall_packages;distroless_add()вызываетdistroless-builder.py add, создаётdistroless.tar, распаковывает его в/rootfsи удаляет дубли относительно/basefs;- второй
FROMберёт финальный базовый образ изdistroless.from; COPY --from=builder /rootfs/ /переносит подготовленный минимальный rootfs в финальный образ;distroless_config()добавляетENV,USER,WORKDIR,ENTRYPOINT,CMDиз секцииdistroless;LABELдобавляет OCI metadata в сам образ.
distroless.tar
distroless.tar - временный tar-архив rootfs, который создаётся только в builder-стадии.
Его создаёт distroless-builder.py:
distroless-builder.py add ...получает правила изdistroless.rootfs: конкретные файлы, файлы из rpm-пакетов, библиотеки бинарников, списки файлов.- Скрипт сохраняет список найденных путей во внутреннем рабочем состоянии.
distroless-builder.py tar -o distroless.tarупаковывает эти пути в tar-архив.- Dockerfile распаковывает архив командой
tar -C /rootfs -xf distroless.tar. - Финальная стадия копирует
/rootfsв образ черезCOPY --from=builder /rootfs/ /.
В distroless-true архив содержит файл /bin/true, нормализованный под ALT usrmerge. На
практике это означает, что основной файл оказывается в /usr/bin/true, а путь /bin в
итоговом rootfs остаётся совместимым symlink'ом.
altflow-test
Общий формат файла описан в спецификации образов. Для distroless-образов тест должен быть безопасным: команда должна быстро завершаться и не требовать shell, сети или Kubernetes API, если shell не добавлен в образ явно.
[
[
"/bin/true"
]
]
Если в образе нет /bin/true, не используйте его в тесте. Проверяйте реальный entrypoint
или другой файл, который действительно попадает в rootfs.