Главный плюс развертывания приложений в виде легковесных контейнеров – это то, что контейнерный образ содержит все зависимости, необходимые для работы приложения. Однако это преимущество легко теряется, если образа получается слишком большим и, как следствие, загрузка приложений занимает ощутимое время. Сегодня расскажем, как правильно создавать контейнеры для приложений, используя в качестве основы универсальные базовые образы Red Hat (Universal Base Images, UBI). Кроме того, рассмотрим лучшие практики создания и хранения таких образов согласно требованиям сертификации Red Hat.

Сборка контейнеризованных приложения с использованием UBI

Универсальные базовые образы Red Hat – это легковесная и безопасная основа для создания облачных и веб-приложений в контейнерах, которая обеспечивает надежность, безопасность, производительность и управление жизненным циклом контейнерных образов. На основе UBI можно создавать свои контейнерные приложения, размещать их на серверах реестра, легко делиться им и даже развертывать на платформах, отличных от Red Hat.

В основе UBI-образов лежит Red Hat Enterprise Linux (RHEL), самый популярный Linux-дистрибутив корпоративного класса в последние лет 20. Создавая свои контейнерные образы на основе UBI, можно быть уверенным в их надежности и безопасности, а также совершенно свободно и бесплатно распространять их, причем для этого вовсе не обязательно быть клиентом Red Hat

Где взять UBI-образы

В двух местах: в нашем каталоге Red Hat Container Catalog и в официальном репозитории Red Hat на Docker Hub. Советуем использовать Red Hat Container Catalog, поскольку консоль этого каталога позволяет быстро узнать размер образа, его версию, работоспособность (health-индекс), перечень входящих в него пакетов, Dockerfile, а также выбрать один из несколько вариантов образа, как показано на иллюстрации ниже.

Сведения об образе в консоли Red Hat Container Catalog
Сведения об образе в консоли Red Hat Container Catalog

Какие бывают UBI-образы

Есть следующие типы UBI-образов:

  • Micro – максимально урезанный образ, у которого нет даже своего менеджера пакетов. Для установки пакетов используется менеджер пакетов хоста, на котором развертывается образ; обычно это делается с помощью Buildah или многоэтапных сборок Podman.

  • Minimal – урезанный образ с менеджером пакетов microdnf.

  • Standard – спроектирован и сконструирован так, чтобы служить базовым слоем для контейнерных приложений, связующего ПО или утилит.

  • Init: – предназначен для запуска системы в качестве PID 1 (процесс Linux init) для выполнения мультисервисов внутри контейнера.

Подробнее информация по типам UBI-образов приведена в таблице:

 

Тип UBI

Размер (сжатый)

Размер (несжатый)

Health-индекс

Соответствие OCI

Кто поддерживает

Пакетов в образе

Базовая ОС

Команда Pull

Micro

12.9 МБ

35.0 МБ

A

Да

Red Hat

18

RHEL 8.4

docker pull registry.access.redhat.com/ubi8/ubi-micro

Minimal

37.5 МБ

97.7 МБ

A

Да

Red Hat

101

RHEL 8.4

docker pull registry.access.redhat.com/ubi8/ubi-minimal

Standard

79.5 МБ

215.0 МБ

A

Да

Red Hat

190

RHEL 8.4

docker pull registry.access.redhat.com/ubi8/ubi

Init

84.5 МБ

232.1 МБ

A

Да

Red Hat

192

RHEL 8.4

docker pull registry.access.redhat.com/ubi8/ubi-init

Контейнерные образы для runtime-компонентов

Покажем, как сформировать образы на основе UBI для runtime-компонентов на языках программирования Golang и Python. Варианты тестового приложения для обоих этих языков (вместе с Dockerfile) можно найти здесь, а ниже мы просто покажем, как упаковать это приложение в UBI-образ.

Сборка и запуск Golang-приложения с использованием UBI

Начнем с Dockerfile:

FROM golang AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY ./app.go ./go.mod ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -o app .

FROM registry.access.redhat.com/ubi8/ubi-micro
WORKDIR /
COPY --from=builder /go/src/github.com/alexellis/href-counter/app /
EXPOSE 8080
CMD ["./app"]

Здесь мы используем многоэтапную сборку, популярный способ создания контейнерных образов из Dockerfile. В первой секции Dockerfile задается официальный образ Golang, во второй – официальный UBI-образ. На примере этого Dockerfile видно, что UBI можно легко использовать вместе с другими базовыми образами.

Теперь, чтобы упаковать наше Golang-приложение в UBI-образ, воспользуемся командой FROM для задания базового образа, в данном случае официального micro-образа UBI. Команда WORKDIR указывает каталог нашего приложения внутри контейнерного образа. Команда COPY копирует двоичный файл Golang-приложения в UBI-образ, а команда EXPOSE задает порт, который будет прослушиваться приложением. И наконец, CMD задает команду, которая будет выполняться при запуске контейнера.

Итак, Dockerfile готов. Теперь соберем и запустим образ:

git clone ksingh7/dockerfile-hub.git
cd dockerfile-hub/go-hello-world-app-ubi
docker build -t go-hello-world-app-ubi .
docker images | grep -i go-hello-world-app-ubi
docker run -it -p 8080:8080 -d go-hello-world-app-ubi
curl http://localhost:8080

Вывод команды cURL будет выглядеть так:

Hello OpenShift!

Проверим размер финального образа – всего 42.8 МБ:

$ docker images
REPOSITORY              TAG     IMAGE ID       CREATED          SIZE
go-hello-world-app-ubi  latest  ac7f4c163f5c   6 hours ago      42.8MB

Сборка и запуск Python-приложения с использованием UBI

Теперь проделаем то же самое для приложения Python. Вот как выглядит Dockerfile:

FROM registry.access.redhat.com/ubi8/ubi-minimal
RUN microdnf install -y python3
WORKDIR /app
COPY ./requirements.txt ./app ./
RUN python3 -m pip install -r /app/requirements.txt
EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

Для Python’а мы используем классический Dockerfile, поскольку он проще для понимания. В качестве базового образа здесь применяется официальный minimal-образ UBI. Команда microdnf устанавливает runtime-среду Python. Команда WORKDIR указывает каталог нашего приложения внутри контейнерного образа. Команда COPY копирует файл требований Python в UBI-образ, который затем будет использоваться командой RUN для установки зависимостей. Команда EXPOSE задает порт, который будет прослушиваться приложением. И наконец, CMD задает команду, которая будет выполняться при запуске контейнера.

Вот как это работает:

# Clone the git repo if you have not already done
git clone ksingh7/dockerfile-hub.git
cd dockerfile-hub/python-hello-world-app-ubi
docker build -t python-hello-world-ubi .
docker images | grep -i python-hello-world-ubi
docker run -it -p 8080:8080 -d python-hello-world-ubi
curl http://localhost:8080

Вывод команды cURL будет выглядеть так:

{"Hello":"World"}

Размер финального образа – 169 МБ:

$ docker images
REPOSITORY              TAG     IMAGE ID       CREATED          SIZE
python-hello-world-ubi  latest  50c12e1ca549   55 minutes ago   169MB

Как создавать образы, отвечающие требованиям Red Hat Container Certification

Создавать и поддержать отдельные образы для каждой платформы оркестрации – это слишком хлопотно и дорого. Лучше иметь единый образ, который, с одной стороны, реализует преимущества поддержки и безопасности Red Hat OpenShift, а с другой – хорошо работает и на платформе Kubernetes.

Универсальный образ приложения (universal application image, UAI) – это образ, который построен на основе UBI и включает в себя само приложение, а также дополнительные элементы, улучшающие его безопасность и масштабируемость в Kubernetes и OpenShift. Кроме того, такой образ можно сертифицировать по партнерской программе Red Hat Container Certification, чтобы он вошел в состав контейнерной экосистемы Red Hat.

Ниже мы разберем девять лучших практик создания UAI-образов.

Лучшая практика №1: UAI создается на основе UBI

Базовый контейнерный образ, который вы используете для своего приложения, содержит необходимые этому приложению Linux-библиотеки. Поэтому выбор базового образа непосредственно влияет на универсальность, безопасность и эффективность создаваемого контейнера приложения.

UBI гарантирует, что ваш UAI будет работать как в Kubernetes, так и в OpenShift, а также будет соответствовать требованиям Open Container Initiative (OCI). Кроме того, его можно будет свободно распространять и он будет иметь официальную поддержку Red Hat при работе на платформе OpenShift.

Сборка из UBI

Команда FROM в вашем Dockerfile должна создавать образ приложения из образа UBI. Если компьютер, на котором производится сборка образа, имеет выход в интернет, то UBI-образ можно загрузить непосредственно из реестра Red Hat:

FROM registry.access.redhat.com/ubi8/openjdk-11:1.3-15

Требования Red Hat Container Certification

В базовом образе должны использоваться Linux-библиотеки из состава Red Hat Enterprise Linux. Этому требованию отвечает как базовый образ RHEL, так и UBI-образы. Подробнее см, документацию Red Hat.

Базовые образы Red Hat доступны в реестре сертифицированных контейнерных образов Red Hat. Образы в пространстве имен ubi8 включают библиотеки из RHEL 8. В этом реестре есть UBI-образы для различных языковых runtime-сред.

Если там нет UBI-образа для нужной вам языковой среды, то используйте в качестве отправной точки minimal-образ ubi8 (registry.access.redhat.com/ubi8/ubi-minimal) и установите на него необходимые языковые runtime-компоненты.

Дополнительные сведения можно найти в руководстве для партнеров Containers and the Red Hat Universal Base Images (UBI), а также в электронной книге Red Hat Universal Base Images (UBI).

Лучшая практика №2: запуск образа от имени не-root пользователя

Если процесс, запущенный от имени root, вдруг вырвется из контейнера, то получает root-доступ к хост-машине. Поэтому на всякий случай контейнер должен запускаться только от имени не-root пользователя.

По умолчанию Docker собирает и запускает образ от имени root (то есть UID=0). Чтобы так не было, в Dockerfile для сборки образа надо указывать UserID, отличный от 0.

Когда Kubernetes запускает контейнер, его процессы запускаются от UserID, который указан в Dockerfile.

Запуск образа от имени не-root пользователя

Указать пользователя в Dockerfile можно с помощью команды USER, например, USER 1001.

В лучших практиках Dockerfile отмечается, что если вы задает пользователя не через username , а через UID, то не нужно вносить пользователя или группу в системный файл passwd или group. Однако, если в базовом образ указывается не-root пользователь, то следует указать имя этого пользователя. Например, UBI определяет пользователя с именем default.

Требования Red Hat Container Certification

Red Hat рекомендует, чтобы образ задавал не-root пользователя. При запуске контейнера в OpenShift, оркестратор запустит его процессы от имени произвольного не-root пользователя.

Когда вы собираете образ на основе UBI с языковой runtime-средой, то пользователь там уже задан как не root-пользователь с именем default.

Лучшая практика №3: права владельца для группы и разрешения на файлы

Если процессу нужен доступ к файлам в локальной файловой системе контейнера, то для доступа к этим файлам пользователь и группа процесса должны быть их владельцами. В OpenShift пользователь, от имени которого запускается контейнер, назначается произвольно, но этот произвольный пользователь всегда является членом группы root. Поэтому группе root надо назначить права владельца на локальные файлы, чтобы произвольный пользователь имел к ним доступ.

Установка разрешений на файлы и прав владельца для группы

В Dockerfile надо установить разрешения на каталоги и файлы, которые использует процесс. Группа root должна иметь права владельца на эти файлы и права на чтение и запись. Иначе говоря, Dockerfile выглядит следующим образом, где /some/directory-– это каталог с файлами, к которым процесс должен иметь доступ:

RUN chown -R 0 /some/directory && \
    chmod -R g=u /some/directory

Для совместимости с Kubernetes в Dockerfile следует указать UserID не-root пользователя, а затем прописать в качестве владельца файлами этот UserID и группу root:

USER 1001
RUN chown -R 1001:0 /some/directory

В сочетании эти два подхода работают как для Kubernetes, так и для OpenShift:

USER 1001
RUN chown -R 1001:0 /some/directory && \
    chmod -R g=u /some/directory

Например, если база данных Cassandra хранит данные в каталоге /etc/cassandra, то в Dockerfile для сборки образа для OpenShift надо прописать следующие инструкции:

USER 1001
RUN chown -R 1001:0 /etc/cassandra && \
    chmod -R g=u /etc/cassandra

Требования Red Hat Container Certification

В Red Hat Container Certification нет требований по предоставлению или отзыву прав владельца для группы и файловых разрешений.

Pod’ы в кластере OpenShift запускаются от имен произвольного UserID, входящего в группу root. В руководстве по OpenShift Container Platform написано следующее:

Чтобы образ мог работать от имени произвольного пользователя, каталоги и файлы, в которые процессы образа производят запись, должны иметь в качестве владельца группу root и быть доступны этой группе для чтения/записи. Файлы, которые будут запускаться, также должны иметь разрешения на выполнение для этой группы.

Если процесс использует какие-то файлы совместно с другими процессами и поэтому должен работать от имени конкретного пользователя или группы, которые имеют права владельца на эти файлы, то его pod должен определять контекст безопасности, в котором будет указаны этот пользователь или группа. Кроме того, в кластере должен быть задан набор ограничений контекста безопасности, разрешающий указать этого пользователя или группу. Подробнее см. Getting started with security context constraints on Red Hat OpenShift.

Лучшая практика №4: многоэтапное создание образов

Развертываемый образ должен содержать приложение и его языковую runtime-среду, однако в нем не должно быть инструментов, применяемых при сборке приложения, и любых библиотек, которые не используются при выполнении приложения. Вместо этого создается двухэтапный Dockerfile, задающий отдельные образы, один для сборки артефактов, другой – для хостинга самого приложения.

Многоэтапное создание образов

Для многоэтапной сборки образа, в Dockerfile надо прописать несколько строк FROM, по одной на каждый этап. На последнем этапе создается финальный файл образа, а процесс сборки отбрасывает образы, созданные на предыдущих этапах. Как правило, каждому этапу, кроме последнего, присваивается имя, чтобы последующим этапам было проще обращаться к артефактам, которые были созданы на предыдущих.

Например, многоэтапная сборка обычно состоит из двух этапов, один из которых создает артефакты приложения, а другой – образ приложения. Первый этап обычно называется builder. В документации Docker по многоступенчатым сборкам приводится такой пример:

FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

Работает это следующим образом:

  • Первый этап называется builder и начинается с образа Go, где уже установлены инструменты сборки Go.

  • Второй этап, на котором создается образ для развертывания приложения, начинается с образа Alpine и не нуждается в собственном имени.

  • На первом этапе создается приложение с именем app в каталоге с именем /go/src/github.com/alexellis/href-counter/.

  • На втором этапе файл /go/src/github.com/alexellis/href-counter/app с этапа builder копируется в текущий каталог этапа развертывания.

Требования Red Hat Container Certification

В Red Hat Container Certification нет требований относительно использования многоступенчатых Dockerfile.

Лучшая практика №5: использование в образе последних обновлений безопасности

Linux-библиотеки в образе должны содержать последние на момент создания образа исправления безопасности. Добиться этого можно следующим образом:

  • Всегда использовать последний релиз базового образа и при появлении нового релиза пересобирать на его основе образ приложения.

  • Проводить сканирования уязвимостей, проверяя базовые образы или образы приложений на предмет известных уязвимостей. Обычно для этого используют такие инструменты, как Trivy, Clair и Vulnerability Advisor.

  • Устанавливать исправления безопасности. Иначе говоря, обновлять Linux-компоненты, используя менеджер пакетов ОС, в Red Hat Linux это yum и dnf. Dockerfile может запускать менеджер пакетов в ходе сборки образа.

Сборка образа с последними исправлениями безопасности

Собирая образ приложения с использованием последнего релиза UBI, вы получаете компоненты с последними на момент выхода этого релиза обновлениями безопасности.

Если же в UBI надо добавить исправления, которые появились позднее, это можно сделать с помощью команды RUN:

FROM registry.access.redhat.com/ubi8/openjdk-11:1.3-15
USER root
RUN dnf -y update-minimal --security --sec-severity=Important --sec-severity=Critical && \
    dnf clean all
USER default

Требования Red Hat Container Certification

Для прохождения сертификации компоненты Red Hat в контейнерном образе не должны содержать критических или важных на момент сертификации уязвимостей безопасности.

Подробнее о классификации уязвимостей безопасности можно почитать здесь. Чтобы обновить компоненты Red Hat и установить необходимые исправления, можно вставить следующую команду в Dockerfile вашего образа:

RUN yum -y update-minimal --security --sec-severity=Important --sec-severity=Critical

Лучшая практика №6: создание информативных описаний образов

Образы должны четко идентифицироваться, чтобы можно было легко понять, как он называется, что он делает и кто его создал. Эти сведения должны быть неотъемлемой частью образа.

Использование меток в образах

Метки задаются в Dockerfile командой LABEL. Вот как, например, задаются метки, необходимые для сертификации Red Hat:

LABEL name="my-namespace/my-image-name" \
      vendor="My Company, Inc." \
      version="1.2.3" \
      release="45" \
      summary="Web search application" \
      description="This application searches the web for interesting stuff."

Требования Red Hat Container Certification

По условиям Red Hat Container Certification в образе должны быть следующие метки:

  • name – имя образа.

  • vendor – название компании.

  • version – версия образа.

  • release – число, идентифицирующее сборку образа.

  • summary – краткое описание приложения или компонентов в этом образеe.

  • description – более длинное описание приложения или компонентов в этом образe.

Метки задаются в Dockerfile с помощью команды LABEL. Если образ создается на основе UBI, то эти метки в нем уже есть и их значения заданы компанией Red Hat. А вы должны переопределить их, используя значения для своего образа.

Лучшая практика №7: встраивание в образ файлов лицензии

В отрасли нет какого-то единого стандарта на то, как встраивать текст лицензии в состав ПО. Однако легко можно хранить текстовые файлы лицензии прямо в образе. В результате, образ становится самодокументирующимся и позволяет пользователю легко получить сведения о лицензии на ПО, которое содержится в образе.

GitHub может отображать лицензию репозитория при соблюдений следующих условий:

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

  • Раздел Добавление лицензии в репозиторий объясняет, что GitHub может обнаруживать и отображать лицензию репозитория, если файл лицензии хранится в домашнем каталоге репозитория и называется LICENSE или LICENSE.md (все символы заглавные).

Добавление лицензии в образ

Каталог с исходным кодом, где лежит Dockerfile, также должен также включать каталог с файлами лицензии. Обычно в этом каталоге есть по крайней мере один файл с именем LICENSE.txt. Каталог выглядит следующим образом:

$ ls -ld licenses Dockerfile
-rw-r--r-- 1 bwoolf staff 774 May 5 15:07 Dockerfile
drwxr-xr-x 3 bwoolf staff 96 May 5 15:09 licenses
$ ls -l licenses
total 8
-rw-r--r-- 1 bwoolf staff 17 May 5 15:10 LICENSE.txt

Следующий код в Dockerfile добавляет этот каталог лицензий в образ:

COPY licenses /licenses

Требования Red Hat Container Certification

Red Hat требует, чтобы файл(ы) лицензии хранились в образе в каталоге/licenses. Удобно создать соответствующий каталог лицензий в домашнем каталоге репозитория, который Dockerfile будет просто копировать.

Чтобы соблюсти требования и GitHub, и Red Hat, можно хранить две копии файла лицензии, одну в LICENSE для GitHub, другую – в licenses/LICENSE.txt для Red Hat.

Лучшая практика №8: сохранение исходных слоев базового образа

При создании образа приложения не надо изменять, заменять или комбинировать пакеты или слои в базовом образе. За одним исключением: процесс сборки может и должен обновлять пакеты безопасности в библиотеках Linux на последние обновления.

Метаданные контейнерного образа должны четко показывать, что образ включает слои базового образа, не изменяет их, а только дополняет.

Сохранение слоев исходного образа в Dockerfile

Dockerfile обычно строится на основе базового образа и добавляет к нему новые слои. Приложение должно работать поверх операционной системы, но не заменять ее.

Требования Red Hat Container Certification

Требования Red Hat Container Certification запрещают модификацию слоев в базовом образе Red Hat. Когда в качестве базового слоя используется UBI, Red Hat поддерживает использование и расширение слоя UBI.

Подробнее см. Red Hat Container Support Policy.

Лучшая практика №9: ограничение на количество слоев в образах

Слои в образе –это хорошо, но только если их не слишком много. Рекомендуется создавать образы с 5-20 слоями (включая слои базового образа). 30 слоев – еще допустимо, 40 и больше – перебор, ими будет сложно управлять.

Ограничение на количество слоев в образах

Количество слоев в образе зависит от того, как он создается. Чтобы вывести список слоев в образе, используйте CLI-интерфейс Docker:

docker history <container_image_name>

Или Podman:

 podman history <container_image_name>

Например, образ ubi8/openjdk-11:1.3-15 содержит три слоя:

$ docker pull registry.access.redhat.com/ubi8/openjdk-11:1.3-15
$ docker history registry.access.redhat.com/ubi8/openjdk-11:1.3-15

IMAGE          CREATED       CREATED BY   SIZE      COMMENT

a9937ea40626   7 days ago                 509MB

<missing>      13 days ago                4.7kB

<missing>      13 days ago                103MB     Imported from -

Требования Red Hat Container Certification

Согласно требованиям Red Hat Container Certification, образ должен содержать не более 40 слоев. UBI-образы Red Hat имеют очень мало слоев, что позволяет легко выдерживать это требование при сборке своих образов.

Что еще почитать по сертификации контейнерных образов

Сборка и хранение UAE-образов на платформе OpenShift

Теперь рассмотрим, как использовать конвейер сборки, чтобы реализовать еще две лучшие практики: автоматизацию соблюдения требований Open Container Initiative (OCI) и маркировку каждого образа уникальным идентификатором. Использование конвейера сборки для создания и хранения образов автоматизирует процесс, делая его повторяемым и надежным.

В двух словах о конвейерах CI/CD

Напомним, что конвейер сборки выполняет непрерывную интеграцию в конвейере, который обеспечивает непрерывную доставку в рамках жизненного цикла разработки ПО. Каждый раз, когда код программного компонента изменяется, конвейер CI выполняет сборку ПО, упаковывает его для развертывания и выполняет развертывание в среде разработки или тестирования.

Что делает конвейер CI/CD:

  • Проверяет, что последнюю версию кода можно собрать и развернуть.

  • Гарантирует, что в развернутом компоненте всегда используется последняя версия кода.

  • Выполняет проверку качества кода.

  • Предотвращает развертывание, если ПО не отвечает приемлемому уровню качества.

Лучшая практика №1: сборка образов согласно требованиям OCI

Open Container Initiative (OCI) –это независимы орган, который регулирует открытые отраслевые стандарты на формат контейнерных образов, способы хранения и распространения образов и способа запуска образов в качестве контейнеров.

Выполнение требований OCI позволяет создавать вендор-нейтральные образы, которые могут запускаться как любой OCI-совместимой платформе, такой как containerd или CRI-O.

Требования Red Hat Container Certification

Red Hat не требует, чтобы образы создавались с помощью каких-то конкретных инструментов, но все же рекомендует использовать для создания, передачи и запуска OCI-совместимых образов следующий набор инструментов с открытым кодом: Buildah, Skopeo и Podman. В данный момент с этими инструментами проще всего работать на платформе Linux, поддержка Windows и MacOS реализована в меньшем объеме.

Buildah применяется для сборки образов, а Skopeo – для копирования образов между реестрами. Podman также можно использовать для локального запуска образов, хотя это и не имеет значения при развертывании образов на платформе оркестрации контейнеров. OpenShift поддерживает использование Buildah для сборки образов как часть интегрированного процесса сборки с использованием всех этих трех инструментов.

Сборка образов с использованием Buildah

Для сборки образов применяется Buildah-команда bud:

buildah bud -f Dockerfile .

bud – это аббревиатура от «build using dockerfile». Buildah использует файл, содержащий инструкции по сборке, будь то Dockerfile или Containerfile. И в том, в другом случае используется один и тот же синтаксис.

Лучшая практика №2: маркировка каждого образа уникальным идентификатором

При добавлении образа в реестр, его надо промаркировать тегом, указывающим версию ПО и релиз сборки внутри образа.

Требования Red Hat Container Certification

Согласно требованиям Red Hat Container Certification, образ должен иметь какой-то тег (за исключением тега latest, который создается автоматически), который однозначно идентифицирует его среди других образов с таким же именем. Обычно тег – это версия образа.

Маркировка образов с помощью тегов

Для добавления тега к образу используется команда tag. Образ может иметь несколько тегов, которые являются псевдонимами для одного и того же файла образа, например:

  1. Собираем образ my-image.

  2. Маркируем его для реестра my-registry и пространства имен my-namespace с указанием версии 1.0 и релиза 1.

  3. А теперь маркируем его без указания номера релиза, а просто как последний релиз этой версии.

  4. Отправляем все теги в удаленный реестр my-registry.

На языке команд это будет выглядеть следующим образом:

docker build -t my-image .
docker tag my-image my-registry/my-namespace/my-image:1.0-1
docker tag my-image my-registry/my-namespace/my-image:1.0
docker push --all-tags my-registry/my-namespace/my-image

В результате, у этого образа будут два тега:

  • 1.0-1 – релиз 1 версии 1.0.

  • 1.0 – просто последний релиз версии 1.0.

При этом, в реестре по идее не должно быть образа с тегом 1.0-1. Если там такой уже есть, то он лишиться этого тега. Если бы использовался тег 1.0-2, то в реестре скорее всего уже были бы образы с тегами 1.0-1 и 1.0. Тогда если раньше тег 1.0 указывал на образ 1.0-1, то теперь он указывает на образ 1.0-2. Аналогичным образом, можно добавить тег 1, чтобы сказать, что последний образ – это версия 1.x. Например, если посмотреть все теги для различных сборок образа ноды в DockerHub. то можно увидеть, что одна и та же сборка часто имеет несколько тегов, которые действуют для нее как псевдонимы.

Идентификаторы образа в реестре должны совпадать с его внутренними идентификаторами. Образ должен содержать три следующих идентификационных поля:

  • name – имя образа.

  • version – версия образа.

  • release – номер-идентификатор конкретной сборки этого образа.

Чтобы идентификаторы реестра совпадали, образ надо промаркировать такими же значениями идентификаторов:

docker tag <registry>/<namespace>/<name>:<version>-<release>

Где <registry> и <namespace> указывают место хранения образа.

Комментарии (0)