Создание образов
Узнайте, как создавать собственные контейнерные образы на основе предварительно собранных образов, которые готовы помочь вам. Процесс включает изучение лучших практик написания образов, определение метаданных для образов, тестирование образов и использование пользовательского рабочего процесса сборки для создания образов, которые можно использовать с Alauda Container Platform Registry. После создания образа вы можете отправить его в Alauda Container Platform Registry.
Содержание
Изучение лучших практик контейнеровОбщие рекомендации по контейнерным образамВключение метаданных в образыОпределение метаданных образаИзучение лучших практик контейнеров
При создании контейнерных образов для запуска на Alauda Container Platform автору образа следует учитывать ряд лучших практик, чтобы обеспечить хороший опыт для пользователей этих образов. Поскольку образы предназначены быть неизменяемыми и использоваться как есть, следующие рекомендации помогают гарантировать, что ваши образы будут легко использоваться и хорошо восприниматься на Alauda Container Platform.
Общие рекомендации по контейнерным образам
Следующие рекомендации применимы при создании контейнерного образа в целом и не зависят от того, используются ли образы на Alauda Container Platform.
Повторное использование образов
По возможности базируйте свой образ на подходящем исходном образе, используя инструкцию FROM. Это гарантирует, что ваш образ сможет легко получать исправления безопасности из исходного образа при его обновлении, вместо того чтобы вам самим обновлять зависимости напрямую.
Кроме того, используйте теги в инструкции FROM, например, alpine:3.20, чтобы пользователи точно знали, на какой версии образа основан ваш образ. Использование тега, отличного от latest, гарантирует, что ваш образ не подвергнется несовместимым изменениям, которые могут появиться в последней версии исходного образа.
Поддерживайте совместимость внутри тегов
При тегировании собственных образов старайтесь сохранять обратную совместимость внутри одного тега. Например, если вы предоставляете образ с именем image, который в настоящее время включает версию 1.0, вы можете использовать тег image:v1. При обновлении образа, если он остается совместимым с исходным, вы можете продолжать использовать тег image:v1, и потребители этого тега смогут получать обновления без сбоев.
Если позже вы выпускаете несовместимое обновление, переключитесь на новый тег, например image:v2. Это позволяет потребителям самостоятельно переходить на новую версию, не подвергаясь неожиданным сбоям из-за несовместимых изменений. Любой потребитель, использующий image:latest, принимает на себя риск любых несовместимых изменений.
Избегайте запуска нескольких процессов
Не запускайте несколько сервисов, таких как база данных и SSHD, внутри одного контейнера. Это не нужно, так как контейнеры легковесны и их легко связать вместе для оркестрации нескольких процессов. Alauda Container Platform позволяет легко размещать и совместно управлять связанными образами, группируя их в один pod.
Такое совместное размещение обеспечивает общий сетевой неймспейс и хранилище для связи между контейнерами. Обновления также менее разрушительны, так как каждый образ можно обновлять реже и независимо. Обработка сигналов также становится проще с одним процессом, так как не нужно управлять маршрутизацией сигналов к дочерним процессам.
Используйте exec в обёрточных скриптах
Многие образы используют обёрточные скрипты для настройки перед запуском основного процесса программного обеспечения. Если ваш образ использует такой скрипт, он должен использовать exec, чтобы процесс скрипта был заменён вашим программным процессом. Если не использовать exec, сигналы, отправленные вашим контейнерным рантаймом, будут направлены скрипту, а не процессу вашего ПО. Это нежелательно.
Например, если у вас есть обёрточный скрипт, который запускает серверный процесс. Вы запускаете контейнер, например, с помощью podman run -i, который запускает скрипт, а тот — ваш процесс. Если вы хотите закрыть контейнер с помощью CTRL+C, и если скрипт использовал exec для запуска сервера, podman отправит SIGINT серверному процессу, и всё будет работать как ожидается. Если exec не использовался, podman отправит SIGINT процессу скрипта, а ваш процесс продолжит работу, как будто ничего не произошло.
Также учтите, что ваш процесс работает как PID 1 в контейнере. Это означает, что если основной процесс завершится, весь контейнер остановится, прерывая любые дочерние процессы, запущенные из процесса с PID 1.
Очистка временных файлов
Удаляйте все временные файлы, созданные во время сборки. Это также касается файлов, добавленных с помощью команды ADD. Например, выполняйте команду yum clean после операций yum install.
Вы можете предотвратить попадание кэша yum в слой образа, создавая команду RUN следующим образом:
Обратите внимание, что если написать так:
то первый вызов yum оставит лишние файлы в этом слое, и эти файлы не смогут быть удалены при последующем выполнении yum clean. Лишние файлы не видны в итоговом образе, но присутствуют в базовых слоях.
Текущий процесс сборки контейнеров не позволяет команде, выполненной в более позднем слое, уменьшить занимаемое пространство, если что-то было удалено в более раннем слое. Однако это может измениться в будущем. Это означает, что если вы выполняете команду rm в более позднем слое, хотя файлы скрываются, общий размер образа для загрузки не уменьшается. Поэтому, как и в примере с yum clean, лучше удалять файлы в той же команде, где они создаются, чтобы они не попадали в слой.
Кроме того, выполнение нескольких команд в одной инструкции RUN уменьшает количество слоев в образе, что улучшает время загрузки и распаковки.
Располагаете инструкции в правильном порядке
Сборщик контейнеров читает Dockerfile и выполняет инструкции сверху вниз. Каждая успешно выполненная инструкция создаёт слой, который может быть повторно использован при следующей сборке этого или другого образа. Очень важно размещать инструкции, которые редко меняются, в начале Dockerfile. Это обеспечивает быструю сборку при повторных запусках, так как кэш не инвалидируется изменениями в верхних слоях.
Например, если вы работаете с Dockerfile, который содержит команду ADD для установки файла, над которым вы ведёте итерации, и команду RUN для установки пакета через yum, лучше поместить команду ADD последней:
Так при каждом изменении myfile и повторной сборке podman build система повторно использует кэш слоя для команды yum и создаёт новый слой только для операции ADD.
Если же написать Dockerfile так:
то при каждом изменении myfile и повторной сборке podman build операция ADD инвалидирует кэш слоя RUN, и команда yum будет выполняться заново.
Отмечайте важные порты
Инструкция EXPOSE делает порт в контейнере доступным для хоста и других контейнеров. Хотя можно указать, что порт должен быть открыт при запуске с помощью podman run, использование инструкции EXPOSE в Dockerfile облегчает использование вашего образа как для людей, так и для программ, явно объявляя порты, необходимые вашему ПО:
- Открытые порты отображаются в выводе
podman psдля контейнеров, созданных из вашего образа. - Открытые порты присутствуют в метаданных образа, возвращаемых командой
podman inspect. - Открытые порты связываются при связывании одного контейнера с другим.
Устанавливайте переменные окружения
Рекомендуется устанавливать переменные окружения с помощью инструкции ENV. Например, можно указать версию вашего проекта. Это облегчает пользователям поиск версии без просмотра Dockerfile. Другой пример — указание пути в системе, который может использоваться другим процессом, например, JAVA_HOME.
Избегайте паролей по умолчанию
Избегайте установки паролей по умолчанию. Многие расширяют образ и забывают удалить или изменить пароль по умолчанию. Это может привести к проблемам безопасности, если пользователь в продакшене получит известный пароль. Пароли лучше настраивать через переменные окружения.
Если вы всё же устанавливаете пароль по умолчанию, убедитесь, что при запуске контейнера выводится соответствующее предупреждение. В сообщении должно быть указано значение пароля по умолчанию и объяснение, как его изменить, например, какую переменную окружения установить.
Избегайте sshd
Лучше не запускать sshd в вашем образе. Для доступа к контейнерам на локальном хосте используйте podman exec. В кластере применяйте kubectl exec для доступа к контейнерам, управляемым Alauda Container Platform. Установка и запуск sshd в образе увеличивает поверхность атаки и усложняет обновления.
Используйте тома для постоянных данных
Образы используют тома для хранения постоянных данных. Таким образом, Alauda Container Platform монтирует сетевое хранилище на узел, где запущен контейнер, и если контейнер перемещается на другой узел, хранилище подключается к новому узлу. Использование тома для всех постоянных данных сохраняет содержимое даже при перезапуске или перемещении контейнера. Если ваш образ записывает данные в произвольные места внутри контейнера, эти данные не сохранятся.
Все данные, которые должны сохраняться после удаления контейнера, должны записываться в том. Контейнерные движки поддерживают флаг readonly для контейнеров, который можно использовать для строгого соблюдения практик, запрещающих запись данных во временное хранилище контейнера. Проектирование образа с учётом этой возможности облегчает её использование в будущем.
Явное определение томов в вашем Dockerfile облегчает пользователям понимание, какие тома необходимо определить при запуске вашего образа.
Дополнительную информацию о томах и их использовании в Alauda Container Platform смотрите в документации Kubernetes.
Примечание:
Даже при использовании постоянных томов каждый экземпляр вашего образа имеет свой собственный том, и файловая система не разделяется между экземплярами. Это означает, что том нельзя использовать для совместного хранения состояния в кластере.
Включение метаданных в образы
Определение метаданных образа помогает Alauda Container Platform лучше использовать ваши контейнерные образы, создавая лучший опыт для разработчиков, использующих ваш образ. Например, вы можете добавить метаданные с полезными описаниями образа или предложениями других образов, которые могут понадобиться.
В этой теме определены только метаданные, необходимые для текущего набора сценариев использования. В будущем могут быть добавлены дополнительные метаданные или сценарии.
Определение метаданных образа
Вы можете использовать инструкцию LABEL в Dockerfile для определения метаданных образа. Метки похожи на переменные окружения тем, что представляют собой пары ключ-значение, прикреплённые к образу или контейнеру. Метки отличаются от переменных окружения тем, что они не видны запущенному приложению и могут использоваться для быстрого поиска образов и контейнеров.
Подробнее об инструкции LABEL смотрите в справочнике Dockerfile.
Имена меток обычно имеют пространство имён. Пространство имён устанавливается в соответствии с проектом, который будет использовать метки. Для Kubernetes пространство имён — io.k8s.