Упростите сборку Docker для ваших приложений Rails с помощью Makefiles



В моей предыдущей статье я обсуждал некоторые из лучших практик для написания файлов Docker, такие как использование entrypoint и уменьшение количества RUN инструкций на файл Docker, а также использование пользовательских базовых образов Docker.

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

$> docker build -t ${IMG}:${IMG_TAG} Dockerfile
$> docker push ${IMG}:${IMG_TAG}

Команды Docker для создания образов просты и удобны в использовании; однако он может быть очень длинным и сложным, особенно если для создания образа Docker требуются дополнительные действия, такие как:

  • Передача аргументов сборки команде docker build
  • Установка зависимостей приложения перед сборкой образа Docker
  • Создание ярлыков для прикрепления к изображениям Docker
  • Перед созданием образа Docker необходимо скомпилировать исходный код.

Вышеупомянутые моменты могут значительно усложнить создание образа Docker, и в результате команда docker build будет более сложной и длинной. Кроме того, в случае управления несколькими приложениями это означает, что каждое из приложений будет иметь свой уникальный набор команд для создания своего образа Docker, особенно если эти приложения созданы с использованием разных языков программирования.

Одна из идей решения этой проблемы - скрыть сложность построения образов Docker за единым интерфейсом для всех сервисов Docker. Требования к этому инструменту или интерфейсу следующие:

  • Сборка и отправка образов Docker должны выполняться простыми командами.
  • Создание и распространение образов Docker в разных сервисах должно выполняться одинаково.

Мы можем реализовать этот интерфейс, просто используя старый инструмент под названием make. Эта команда обычно устанавливается в macOS и в системах Linux и используется для управления и компиляции процесса исходного кода, а также для определения команд, необходимых для компиляции и установки программных приложений. Makefiles - это файлы, которые определяют инструкции по компиляции и сборке исходного кода, который будет использоваться командой make.

Чтобы решить наши проблемы, мы собираемся написать Makefile, который определяет, как создавать и отправлять образы Docker, а затем мы собираемся использовать команду make для выполнения фактического процесса и вызова необходимых docker команд под капотом. .

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

Эти элементы конфигурации можно перезаписать с помощью переменных среды. Например, мы можем настроить пространство имен по умолчанию и по-прежнему создавать образы Docker и отправлять их в другое пространство имен, используя ту же команду make с дополнительной переменной среды, например, make build и NAMESPACE=overwritten make build.

Ниже приведен список некоторых из этих элементов конфигурации с описанием каждого из них.

  • NAMESPACE: пространство имен проекта будет использоваться как пространство имен для образа Docker.
  • REGISTRY: URL-адрес реестра Docker, используемый для размещения образа Docker.
  • BRANCH: ветвь Git, используемая для создания образа Docker. Образ Docker будет помечен именем ветки. Например, образы Docker, созданные из ветки master, будут помечены тегом master, а образы, созданные из ветки develop, будут иметь тег develop.

Ниже приведен список некоторых элементов конфигурации, которые должны быть определены и использованы командами make. Значения этих переменных либо имеют статические значения, например image_name, либо генерируются автоматически с помощью команды Git, например commit_hash.

  • IMAGE_NAME: это должно определять имя образа Docker, и обычно оно может совпадать с именем приложения.
  • IMAGE_FULL_NAME: это полное имя образа Docker, включенное в реестр и пространство имен.
  • BRANCH_TAG: это тег ветки, который будет использоваться для добавления тегов к образу Docker. Этот элемент ретранслирует ветку, но гарантирует, что значение можно использовать в качестве тега, т. Е. Тег не содержит никаких специальных символов, таких как /.
  • COMMIT_HASH: последний хэш фиксации в ветке, использованной для создания образа Docker. Мы можем использовать этот элемент, чтобы пометить образ Docker и добавить метку к образу Docker, чтобы было легче узнать, какая версия кода выполняется внутри образа Docker.
  • COMMAND: команда по умолчанию, поддерживаемая образом Docker. Для приложения Rails это может быть команда rails server.
  • PORT: порты, необходимые для службы. Эти порты будут доступны для хост-системы.
  • CONTAINER_ENV: переменные среды приложения по умолчанию будут связаны с контейнерами, созданными командой make.
  • BUILD_PARAMS: список опций команды docker build.
  • BUILD_ARGS: Список поддерживаемых Docker--build-arg

Следующим шагом будет определение поддерживаемых команд Makefile. Ниже приведен список предлагаемого набора команд make, которые могут значительно упростить сборку, отправку и тестирование образов Docker:

  • make config: эта команда будет использоваться для выполнения всех действий, необходимых для создания образов Docker. Этими действиями могут быть установка пакетов, необходимых для процесса сборки, компиляция исходного кода пакетов или создание файлов конфигурации. Ниже предлагается config реализация приложения Rails, которое упаковывает все драгоценные камни в каталог локального поставщика.
  • make build: эта команда будет использоваться для создания и пометки образа Docker на узле хоста. Ниже предлагается реализация для приложений Rails, которые создают образ Docker и помечают его как COMMIT_HASH, так и BRANCH_TAG.
  • make shell: эта команда создаст новый контейнер из сгенерированного образа Docker и откроет сеанс оболочки внутри контейнера. Ниже предлагается реализация для запуска оболочки sh внутри временного контейнера.
  • make run: эта команда будет использоваться для создания контейнера из сгенерированного образа Docker на переднем плане и для выполнения команды приложения по умолчанию. В приведенном ниже фрагменте кода показана реализация команды run, которая запускает временный контейнер и выполняет команду, определенную в переменной COMMAND внутри контейнера.
run:
  docker run --rm --name ${NAME}-${BRANCH_TAG} ${CONTAINER_ENV} -it ${PORT} ${IMAGE_FULL_NAME}:${COMMIT_HASH} ${COMMAND}
  • make start: эта команда будет использоваться для создания контейнера из сгенерированного образа Docker в фоновом режиме и выполнения команды по умолчанию для приложения. В приведенном ниже фрагменте кода показана реализация команды start, которая запускает контейнер в фоновом режиме с помощью команды, определенной в переменной COMMAND.
  • make stop: эта команда остановит контейнер, созданный командой make start. Это можно сделать просто с помощью команды docker rm -f.
stop:
  docker rm -f ${NAME}-${BRANCH_TAG}
  • make push: эта команда будет использоваться для передачи тегов созданного образа Docker с узла хоста в реестр Docker. Приведенные ниже реализации будут помещать тег ветки и фиксировать хэштеги в реестре Docker. Кроме того, если используемая ветвь является ветвью master, команда push также подтолкнет тег latest.
  • make release: эта команда будет использоваться для автоматизации команд config, build, и push. Обычно он вызывает задачи, определенные в этих подкомандах.
release: config build push
  • make clean: эта команда будет использоваться для удаления всех сгенерированных файлов или образов Docker с помощью команд config и build. Приведенные ниже реализации команды clean удаляют образы Docker, созданные командой build, а также гемсет Ruby, созданный командой config.

Полная реализация Makefile представлена ​​ниже. Эту реализацию можно использовать в качестве шаблона для Docker Makefiles и для создания образов Docker.

Заключение

Makefile помогает упростить создание образа Docker и скрыть сложные команды Docker за простым и легким в использовании интерфейсом. Они помогают стандартизировать способ создания образов Docker в нескольких проектах и, как следствие, помогают создавать простые конвейеры интеграции CI / CD.