Базовые контейнерные образы Fedora/CentOS bootc «с нуля»
Создание базовых образов bootc «с нуля» даёт контроль над содержимым базового образа, позволяя вам управлять потоком ОС и адаптировать среду под конкретные потребности и рабочие процессы.
Хотя основная предпосылка модели bootc заключается в том, что богатое управление настройкой системы Linux может быть достигнуто с помощью «стандартного» контейнера, собранного на основе предоставленного базового образа, который работает в широком диапазоне сред и систем без каких-либо дополнительных накладных расходов, связанных с поддержкой базового образа «с нуля». Кроме того, в рамках стандартного наследования можно заменить ядро и другие фундаментальные компоненты.
Стандартная сборка контейнера
FROM <базовый образ>
RUN ...
Однако некоторые сценарии использования требуют ещё большего контроля, а именно:
-
Организация, собирающая систему bootc, может нуждаться в том, чтобы версия базового образа содержала набор пакетов точно определённых версий.
-
Организация может захотеть начать с минимального базового образа, добавляя только необходимые пакеты.
Цели
Точный контроль версий содержимого
Как организация, развёртывающая систему bootc, я могу хотеть, чтобы версия базового образа содержала набор пакетов точно определённых версий (возможно, определённых файлом блокировки или репозиторием rpm-md). Существует множество инструментов для управления снимками репозиториев yum (rpm-md).
В настоящее время существуют проблемы, из-за которых не совсем работает, например, dnf -y upgrade selinux-policy-targeted.
Сборка на основе минимального
В настоящее время проект производит только один стандартный образ, который теперь известен как «стандартный». Это, по сути, установка, ориентированная на безголовые серверы (хотя она также может использоваться для рабочих столов), и включает множество предопределённых пакетов для работы с сетью, инструментов командной строки и т. д.
Этот проект также имеет определение «минимального» набора содержимого, которое в настоящее время не поставляется в виде отдельного контейнера, но может быть собрано из стандартного образа.
Соображения
Как и многослойные образы bootc, использующие стандартный базовый образ, базовые образы «с нуля» всё равно происходят от базового контейнера. Они не будут автоматически получать изменения стандартного базового образа, если только не являются частью конвейера контейнеров.
Дополнительную информацию о модели обновления bootc см. в обновлении образов bootc здесь и обзоре производных образов здесь.
Если вы пришли из мира «пакетов», вы, возможно, уже используете такие инструменты, как Pulp/Satellite/Artifactory, для создания «снимков/версий» пакетов в вашем базовом образе, что помогает bootc более бесшовно вписаться в ваш существующий рабочий процесс.
Если вы пришли из мира CoreOS, это ключевое различие при работе с базовым образом ОС. Прочитайте о различиях между Fedora CoreOS и Fedora bootc здесь.
Понимание содержимого базового образа
Большая, но не вся часть содержимого базового образа поступает из RPM. Существует некоторое дополнительное не-RPM содержимое, а также постобработка, которая выполняется над корнем файловой системы. В настоящее время реализация сборки базового образа использует rpm-ostree, но это считается деталью реализации, которая может измениться.
Использование bootc-base-imagectl build-rootfs
Основная операция — bootc-base-imagectl build-rootfs.
Эта команда принимает только один обязательный аргумент:
-
Путь к корневой файловой системе, которая будет создана как каталог. Целевой каталог не должен существовать (но его родительский каталог должен существовать).
Кроме того, можно указать --manifest для выбора входного набора пакетов и конфигурации. Два стандартных образа:
-
standard: Стандартный образ. -
minimal: Очень маленький набор содержимого корневой файловой системы, по сутиbootc,systemd,kernel,dnfплюс их жёсткие зависимости, а также небольшой набор изменений не-RPM содержимого, например, для включения постоянного журналирования systemd.
Для получения дополнительной информации о доступных наборах содержимого выполните bootc-base-imagectl list.
В настоящее время прямой набор пакетов официально не поддерживается для непосредственной настройки. Общая идея заключается в том, что вы можете начать с любого образа, а затем добавлять, изменять или удалять содержимое из него на вторичном этапе сборки. Особенно сборка на основе образа minimal должна покрывать многие случаи использования, требующие высокой степени контроля над набором содержимого.
Ключевая цель заключается в том, чтобы по умолчанию избежать «ответвления», гарантируя, что по умолчанию, когда мы изменяем базовый образ (обычно добавляя новые пакеты) или предоставляем обновления или исправления для операции сборки, сборки «с нуля» будут по умолчанию наследовать эти изменения.
Также может быть предоставлен «исходный корень» для включения «кросс-сборок». Подробнее об этом ниже.
Требуются привилегии для сборки
Мы создаём новую корневую файловую систему, а не изменяем существующий контейнер. Это проще всего сделать, используя функции контейнеров (в частности, пространства имён монтирования), которые по умолчанию не включены во многих средах сборки контейнеров.
Таким образом, вы должны предоставить как минимум следующие аргументы, например, для podman build:
--cap-add=all --security-opt=label=type:container_runtime_t --device /dev/fuse
Цель состоит в том, чтобы сократить эти необходимые возможности; см. эту проблему в трекере.
Однако в конечном счёте цель здесь — развернуть этот контейнерный образ как базовую операционную систему в физической или виртуализированной среде, где в любом случае требуется больше доверия.
Пример: Создание базового образа «с нуля» с точным контролем версий
# Начните со стандартного базового образа bootc, который служит «строителем» для нашего образа «с нуля».
FROM quay.io/centos-bootc/centos-bootc:stream10 as builder
# Настройте и переопределите исходные репозитории RPM, если необходимо. Этот шаг требуется при ссылке на определённые представления содержимого или целевые зеркальные/снимки/закреплённые версии содержимого.
RUN rm -rf /etc/yum.repos.d/*
COPY mypinnedcontent.repo /etc/yum.repos.d/
# Соберите корневую файловую систему, используя указанные репозитории и не-RPM содержимое из базового образа «строителя».
# Если репозитории не определены, будет использована стандартная сборка. Вы можете изменить набор пакетов в базовом образе, изменив манифест между наборами "standard" и "minimal".
RUN /usr/libexec/bootc-base-imagectl build-rootfs --manifest=standard /target-rootfs
# Создайте новый пустой образ «с нуля».
FROM scratch
# Скопируйте корневую файловую систему, собранную на предыдущем шаге, в этот образ.
COPY --from=builder /target-rootfs/ /
# Примените настройки к образу. Этот синтаксис использует "heredocs" https://www.docker.com/blog/introduction-to-heredocs-in-dockerfiles/ для передачи многострочных аргументов в более читаемом формате.
RUN <<EORUN
# Установите pipefail для отображения ошибок внутри heredoc и избегайте ложноположительных успешных сборок.
set -xeuo pipefail
# Установите необходимые пакеты, выполните скрипты и т. д.
dnf -y install emacs
# Удалите остатки артефактов сборки от установки пакетов в финальном собранном образе.
dnf clean all
rm /var/{log,cache,lib}/* -rf
# Запустите линтер bootc, чтобы избежать некоторых ошибок и поддерживать качество содержимого. Разместите это как последнюю команду в вашем последнем вызове run.
bootc container lint
EORUN
# Определите обязательные метки для этого образа bootc, чтобы он был распознан как таковой.
LABEL containers.bootc 1
LABEL ostree.bootable 1
# https://pagure.io/fedora-kiwi-descriptions/pull-request/52
ENV container=oci
# Необязательные метки, которые применяются только при запуске этого образа как контейнера. Они сохраняют точку входа по умолчанию работающей под управлением systemd.
STOPSIGNAL SIGRTMIN+3
CMD ["/sbin/init"]
Пример: Создание пользовательского минимального базового образа
# Начните со стандартного базового образа bootc, который повторно используется как «строитель» для пользовательского образа.
FROM quay.io/centos-bootc/centos-bootc:stream10 as builder
# Настройте и переопределите исходные репозитории RPM, если необходимо. Этот шаг не требуется при сборке на основе minimal, если только не ссылаетесь на определённые представления содержимого или целевые зеркальные/снимки/закреплённые версии содержимого.
# Добавьте дополнительные репозитории для применения настроек к образу. Однако ссылка на пользовательский манифест на этом шаге в настоящее время не поддерживается без ответвления кода.
# Соберите корневую файловую систему, используя указанные репозитории и не-RPM содержимое из базового образа «строителя».
# Если репозитории не определены, будет использована стандартная сборка. Вы можете изменить набор пакетов в базовом образе, изменив манифест между наборами "standard" и "minimal".
RUN /usr/libexec/bootc-base-imagectl build-rootfs --manifest=minimal /target-rootfs
# Создайте новый пустой образ «с нуля».
FROM scratch
# Скопируйте корневую файловую систему, собранную на предыдущем шаге, в этот образ.
COPY --from=builder /target-rootfs/ /
# Примените настройки к образу. Этот синтаксис использует "heredocs" https://www.docker.com/blog/introduction-to-heredocs-in-dockerfiles/ для передачи многострочных аргументов в более читаемом формате.
RUN <<EORUN
# Установите pipefail для отображения ошибок внутри heredoc и избегайте ложноположительных успешных сборок.
set -xeuo pipefail
# Установите необходимые пакеты для нашего пользовательского образа bootc.
# Обратите внимание, что использование минимального манифеста означает, что нам нужно добавить критические компоненты, специфичные для нашего случая использования и среды.
# Например, установите сеть и SSH — не каждый случай использования требует SSH, поэтому он не включён в минимальный набор
dnf -y install NetworkManager openssh-server
# Удалите остатки артефактов сборки от установки пакетов в финальном собранном образе.
dnf clean all
rm /var/{log,cache,lib}/* -rf
# Запустите линтер bootc, чтобы избежать некоторых ошибок и поддерживать качество содержимого. Разместите это как последнюю команду в вашем последнем вызове run.
bootc container lint
EORUN
# Определите обязательные метки для этого образа bootc, чтобы он был распознан как таковой.
LABEL containers.bootc 1
LABEL ostree.bootable 1
# https://pagure.io/fedora-kiwi-descriptions/pull-request/52
ENV container=oci
# Необязательные метки, которые применяются только при запуске этого образа как контейнера. Они сохраняют точку входа по умолчанию работающей под управлением systemd.
STOPSIGNAL SIGRTMIN+3
CMD ["/sbin/init"]
Оптимизация контейнерных образов
Эта подкоманда rechunk не поддерживается в rootless podman.
|
Результатом вышеуказанного будет образ с одним большим слоем (tarball), что означает, что каждое изменение приведёт к копированию (отправке в реестр, получению клиентами) одного большого tarball.
В rpm-ostree есть поддержка для обработки большого образа и его «перекомпоновки». Этот процесс оптимизирует порядок и группировку установленных пакетов во многих слоях в финальном образе, что обеспечивает лучшую сетевую эффективность, поскольку несколько слоёв могут быть повторно использованы без необходимости их передачи.
Инструмент bootc-base-imagectl предоставляет подкоманду rechunk для взаимодействия с rpm-ostree и выполнения этой перекомпоновки. Рекомендуется использовать команду bootc-base-imagectl rechunk, а не rpm-ostree напрямую, поскольку детали реализации могут измениться в будущем.
Пример:
В настоящее время bootc-base-imagectl поставляется в составе образов bootc centos-stream. Удобно использовать эти существующие образы для перекомпоновки базовых образов «с нуля». Это можно сделать, подключив хранилище контейнеров хоста в контейнер и запустив bootc-base-imagectl внутри для выполнения операции перекомпоновки.
Ранее собранный базовый образ с именем quay.io/exampleos/fedora-bootc:single можно оптимизировать с помощью следующей команды (от root):
# podman run --rm --privileged -v /var/lib/containers:/var/lib/containers \
quay.io/centos-bootc/centos-bootc:stream10 \
/usr/libexec/bootc-base-imagectl rechunk \
quay.io/exampleos/fedora-bootc:single \
quay.io/exampleos/fedora-bootc:chunked
Пользовательское назначение слоёв с помощью user.component
Перекомпоновщик автоматически группирует файлы в слои на основе принадлежности RPM-пакета. Однако вы можете переопределить это поведение, используя расширенный атрибут user.component, чтобы назначать конкретные файлы или каталоги слоям с пользовательскими именами.
Это полезно, когда у вас есть пользовательское содержимое (не из RPM), которое вы хотите сгруппировать вместе для лучшего кэширования слоёв и повторного использования в разных сборках.
# Назначьте один файл пользовательскому слою
RUN setfattr -n user.component -v "my-apps" /usr/bin/my-custom-app
# Назначьте целое дерево каталогов слою
RUN setfattr -n user.component -v "my-lib" /usr/share/my-lib
Когда для каталога установлен атрибут user.component, все файлы и подкаталоги внутри него автоматически включаются в этот слой. Вы можете переопределить отдельные файлы или подкаталоги, установив для них другое значение user.component:
RUN <<EORUN
set -euxo pipefail
mkdir -p /usr/share/my-lib/docs
# ... заполните каталог ...
# Всё содержимое в my-lib попадает в слой "my-lib"
setfattr -n user.component -v "my-lib" /usr/share/my-lib
# Переопределение: docs попадают в отдельный слой "docs"
setfattr -n user.component -v "docs" /usr/share/my-lib/docs
EORUN
Слои, созданные через user.component, имеют приоритет над автоматическими слоями на основе пакетов во время перекомпоновки.
|
Want to help? Learn how to contribute to Fedora Docs ›