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