Создание образов контейнеров

Образы контейнеров в Fedora собираются с использованием Dockerfile примерно так же, как RPM собирается с использованием spec-файла. В этом разделе приведены рекомендации Fedora по созданию образов контейнеров с использованием Dockerfile.

Пример Dockerfile

FROM registry.fedoraproject.org/fedora:rawhide

ARG NAME=mycontainer
ARG VERSION=0
ARG ARCH=x86_64
LABEL   com.redhat.component="$NAME" \
        name="$FGC/$NAME" \
        version="$VERSION" \
        architecture="$ARCH" \
        run="podman run -p 1337:1337 IMAGE" \
        summary="mycontainer exposes something on port 1337." \
        maintainer="Christian Glombek <lorbus@fedoraproject.org>"

EXPOSE 1337

RUN dnf -y --setopt=tsflags=nodocs install mypackage && \
    dnf clean all

COPY root/help.1 /
COPY script.sh /usr/bin/

CMD ["/usr/bin/script.sh"]

FROM

Согласно справочнику по Dockerfile, инструкция FROM '''должна''' быть первой строкой Dockerfile. Инструкция FROM '''должна''' быть полностью определена с указанием имени реестра Fedora, имени образа и тега, как показано в этом примере:

Это гарантирует, откуда берётся базовый образ при сборке сервисом сборки или при пересборке пользователем.

Для большинства многослойных образов, собираемых https://docs.pagure.org/releng/layered_image_build_service.html[сервисом сборки слоёных образов Docker Fedora], строка FROM будет использовать один из базовых образов Fedora, существующих в https://registry.fedoraproject.org/[реестре контейнеров Fedora]:

``` FROM registry.fedoraproject.org/fedora:latest ```

Также можно использовать другой слоёный образ в качестве базового слоя, как в этом примере:

``` FROM registry.fedoraproject.org/f25/kubernetes-master:latest ```


=== Метки

Dockerfile имеют концепцию https://docs.docker.com/engine/reference/builder/#label[LABEL], которая может добавлять произвольные метаданные к образу в виде пары ключ-значение. Рекомендации Fedora по теме LABEL следуют стандартам http://www.projectatomic.io/[Project Atomic] https://github.com/projectatomic/ContainerApplicationGenericLabels[Container Application Generic Labels] для определения LABEL.

'''Обязательные''' LABEL для слоёного образа Fedora следующие:

[cols="2*", options"header"]
|===
|Имя
|Описание

|com.redhat.component
|Имя компонента в Bugzilla, куда пользователи должны сообщать об ошибках в этом контейнере.

|name
|Имя образа

|version
|Версия образа

|architecture
|Архитектура, для которой предназначено программное обеспечение в образе (Необязательно: если опущено, будет собрано для всех поддерживаемых архитектур Fedora)

|maintainer
|Имя и адрес электронной почты сопровождающего (обычно отправителя)

|run или usage
|Либо предоставляет строку запуска Atomic, либо понятный человеку пример выполнения контейнера

|summary
|Краткое описание образа.
|===

'''Необязательные''' метки для слоёных образов Fedora

[cols="2*", options"header"]
|===
|Имя
|Описание

|install
|Обеспечивает работу команды "atomic install". Не используется для системных контейнеров.

|uninstall
|Обеспечивает работу команды "atomic uninstall". Обязателен, если присутствует Install.

|url
|URL-адрес, где пользователь может найти дополнительную информацию об образе.

|help
|Выполняемая команда, которая приводит к отображению справочной информации.

|atomic.type
|Используется для системных контейнеров, см. ниже.

|Общие
|Любые из https://github.com/projectatomic/ContainerApplicationGenericLabels[Container Application Generic Labels], которые подходят для контейнера, например "stop", "debug" или "changelog-url"
|===

См. СПЕЦИФИКАЦИЮ LABEL ниже для получения более подробной информации о том, что требуется для каждой из этих меток.

{{admon/note|Рекомендации по меткам Dockerfile вышестоящего проекта| Используемые здесь LABEL являются адаптацией Fedora усилий вышестоящего проекта https://projectatomic.io[Project Atomic] по определению https://github.com/projectatomic/ContainerApplicationGenericLabels[Container Application Generic Labels], а также http://docs.projectatomic.io/container-best-practices/[Container Best Practices]. }}

В прошлом эти LABEL должны были определяться в одной строке Dockerfile, чтобы не приводить к появлению дополнительных слоёв при сборке. Последние версии OSBS сжимают все слои, собранные поверх родительского образа, в один слой, что означает отсутствие необходимости размещать все LABEL или команды RUN в одной строке.

Ниже приведён очень простой пример Dockerfile, содержащий обязательные LABEL:

[source]
----
FROM registry.fedoraproject.org/fedora:rawhide

ARG NAME=mycontainer
ARG VERSION=0
ARG ARCH=x86_64
LABEL   com.redhat.component="$NAME" \
        name="$FGC/$NAME" \
        version="$VERSION" \
        architecture="$ARCH" \
        run="podman run -p 1337:1337 IMAGE" \
        summary="mycontainer exposes something on port 1337." \
        maintainer="Christian Glombek <lorbus@fedoraproject.org>"

EXPOSE 1337

RUN dnf -y --setopt=tsflags=nodocs install mypackage && \
    dnf clean all

COPY root/help.1 /
COPY script.sh /usr/bin/

CMD ["/usr/bin/script.sh"]
----


=== СПЕЦИФИКАЦИЯ LABEL

Некоторые дополнительные сведения о том, как заполнять каждую метку.

'''com.redhat.component''': Существующий компонент Bugzilla, в который следует сообщать об ошибках в этом образе.

'''name''': Имя образа. Если образ заменяет стандартный RPM, он должен иметь точно такое же имя, как и этот RPM. В противном случае см. рекомендации по именованию выше.

'''version''': Обычно 0. Заполняется из переменной ARG. См. "ВЕРСИОНИРОВАНИЕ" ниже для объяснения.

'''architecture''': обычно "x86_64", если только образ контейнера не поддерживает другие/все архитектуры.

'''usage''': понятная человеку примерная командная строка для запуска контейнера. Обязателен, если отсутствует run. Должен включать все возможные параметры, такие как порты, тома и любые обязательные параметры командной строки. Вы можете использовать любую среду выполнения контейнеров в качестве примера. Пример из контейнера OwnCloud:

    usage="docker run -d -P -v owncloud-data:/var/lib/owncloud -v owncloud-config:/etc/owncloud owncloud"

'''summary''': Краткое описание образа, предназначенное для поиска, когда у нас будет реестр с функцией поиска. Пожалуйста, включайте соответствующие ключевые слова.

'''run''': командная строка для запуска контейнера, подходящая для использования https://github.com/projectatomic/atomic[Atomic CLI], включая заполнители и встроенный код atomic-run. Должна успешно выполняться на подходящей системе Fedora Atomic. Обязателен, если отсутствует "usage". Пример для контейнера Cockpit:

    run="/usr/bin/docker run -d --privileged --pid=host -v /:/host IMAGE /container/atomic-run --local-ssh"

'''install''': Контейнер может потребовать подготовки хост-системы перед запуском контейнера. В этом случае метка install полезна для определения того, какие операции должны быть выполнены на хосте для его подготовки. Набор операций должен быть максимально минимальным и не должен включать никаких операций, которые не полезны для подготовки хоста к запуску контейнера. Если предоставлена метка install, она должна быть протестирована и работать с https://github.com/projectatomic/atomic[Atomic CLI]. При необходимости также должна быть предоставлена метка uninstall, которая позволит очистить любые операции, выполненные install. Пожалуйста, обратитесь к https://github.com/projectatomic/atomic#atomic-install[документации вышестоящего проекта] для получения дополнительной информации. Пример для контейнера Cockpit:

    install="/usr/bin/docker run --rm --privileged -v /:/host IMAGE /container/atomic-install"

'''uninstall''': Если контейнер имеет метку install, то, скорее всего, потребуется метка uninstall для удаления любых файлов и/или очистки любой конфигурации, которая была выполнена на хост-системе. Не требуется удалять файлы, которые могут содержать пользовательские данные. В необычных случаях может не быть файлов или конфигурации для очистки от метки install, поэтому метка uninstall может не потребоваться. Если предоставлена метка uninstall, она должна быть протестирована и работать с https://github.com/projectatomic/atomic[Atomic CLI]. Пожалуйста, обратитесь к https://github.com/projectatomic/atomic#atomic-uninstall[документации вышестоящего проекта] для получения дополнительной информации.

    uninstall="/usr/bin/docker run --rm --privileged -v /:/host IMAGE /container/atomic-uninstall"

'''url''': URL-адрес, где пользователи могут получить дополнительную информацию об образе, например, репозиторий на github или pagure, или документацию по программному обеспечению.

'''help''': Выполняемая команда, которая выводит man-страницу или другую справочную информацию. Если предоставлена, должна быть протестирована с помощью `atomic help`. Если у вас есть команда help, вам не нужно также предоставлять справочный файл (см. ниже).


=== Версионирование

В предыдущем разделе рассматривались LABEL, одной из которых является версия, устанавливаемая в примере с помощью переменной `ENV` `VERSION`, которая на данный момент должна быть `0`. OSBS автоматически обрабатывает увеличение номера выпуска для данной версии образа контейнера.

На данный момент нет способа автоматически заполнять значение `Version`/`VERSION` значением последней версии основного RPM, принадлежащего образу контейнера. Это то, что в настоящее время https://pagure.io/atomic-wg/issue/249[находится в планах].

Зачем это нужно?

Если мы установим метку `Version` в версию соответствующего RPM на момент проверки образа контейнера, то сопровождающему придётся постоянно обновлять её вручную при каждом обновлении RPM, что неудобно и чревато ошибками. Кроме того, существует вероятность того, что версия RPM может быть обновлена при автоматической пересборке слоёного образа, и сопровождающий не сможет своевременно обновить `Dockerfile` (автоматические пересборки выполняются https://docs.pagure.org/releng/[Release Engineering] для включения обновлений безопасности для всех слоёных образов). Если это произойдёт, то версия образа контейнера не будет соответствовать версии программного обеспечения, которое он должен предоставлять, что приведёт к путанице и, возможно, к неожиданным негативным побочным эффектам для пользователей. Поэтому в настоящее время мы считаем, что номер версии контейнера не имеет значения, но это будет исправлено как можно скорее.


=== CMD / ENTRYPOINT

Ещё одним обязательным элементом является запись CMD или ENTRYPOINT, чтобы при выполнении пользователем следующей команды (например) происходило ожидаемое поведение:

``` docker run registry.fedoraproject.org/f25/myawesomecontainer ```

Для получения дополнительной информации об этих записях, пожалуйста, обратитесь к вышестоящей https://docs.docker.com/engine/reference/builder/[документации по Dockerfile].


=== Тома

Использование томов контейнеров для постоянных данных разрешается и поощряется, но необходимо следовать следующим рекомендациям:

* Любые пользовательские данные, которые могут быть потеряны при обновлении, '''должны''' находиться в томе.
* Любые данные конфигурации приложения, требующие постоянства, '''должны''' находиться в томе. Также разрешена конфигурация с помощью переменных среды, как вместе с томами конфигурации, так и вместо них.
* Все тома, перечисленные в Dockerfile, '''должны''' быть перечислены в справочном файле.
* Пример команды run '''должен''' иметь том с постоянным именем (например, "docker run -d -v owncloud-data:/var/lib/owncloud -v owncloud-config:/etc/owncloud owncloud")
* Тома '''должны''' быть определены как можно более узко. В частности, если образ не предназначен для использования в качестве системного контейнера для системного администрирования, тома должны быть определены таким образом, чтобы монтировать системные каталоги, которые являются исключительными для контейнера. Например, контейнер должен монтировать /etc/application-name/ для файлов конфигурации, а ''не'' /etc/.

Каждый том в справочном файле '''должен''' иметь следующее:
* Полный путь к тому
* Почему он помечен как том (например, почему этой конфигурации требуется постоянство или указание на то, что там находятся пользовательские данные)

Тома, перечисленные в справочном файле, '''должны''' также включать информацию о требованиях к пространству, разрешениям и производительности.

Файл readme '''может''' содержать предлагаемые дополнительные тома, которые не являются обязательными по Dockerfile, например, места для сгенерированных, а не самоподписанных SSL-сертификатов.