Автосборка Docker-образов на коленке: Git -> Jenkins -> Docker Registry

docker: как блинчик испечьСтатья о том, как максимально просто заставить роботов (в нашем случае — Jenkins) собирать Docker-образы на каждый коммит в проект Git-репозитария.

Рассматриваемая схема

Далее описывается реализация следующей схемы:

  1. Разработчик обновляет код проекта
  2. Jenkins обнаруживает это,
  3. Вытаскивает код из git-репы
  4. Собирает Docker-образ
  5. Запихивает его в репозитарий Docker образов (Docker Registry или Docker Hub, в моём случае Nexus Repository)
  6. Сообщает подписчикам о результатах посредством Slack

 

Порядок действий

Разобъём все работы по реализации означенной схемы на три части:

  1. Создание проекта в Git с Dockerfile‘ом в нём
  2. Создание для этого проекта новой Задачи (Job) в Jenkins
  3. Проверяем, что всё сделали верно

Git-репозитарий

В простейшем случае проект может содержать только Dockerfile, если этого достаточно для сборки образа.

bitbucket-dockerfile-repo

Настройки Jenkins

Source Code Management

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

Build Triggers

В этом разделе настроим периодичность проверки нашего проекта в Git на наличие нового коммита.

Jenkins-Build_Triggers

Build

Добавим и настроим Docker Build and Publish plugin

В качестве метки (Tag) Docker-образа воспользуемся SHA-1 хэшем коммита

Jenkins-Build

Post-build Actions

Воспользуемся Slack Notification Plugin для сигнализации об успешной сборке, либо о его крахе.

Jenkins-Post-build_Action

Проверка

Slack

При корректных настройках каждый удачный билд будет радовать нас сообщением в Slack:

Jenkins-Slack_Notification

Docker-клиент

A если у нас кроме Jenkins правильно настроен Docker-репозиторий, то новый образ может быть извлечён с помощью консольного клиента.

 

∗∗∗

В целом на этом всё, далее следуют некоторые подсказки, показавшиеся мне интересными.

Дополнения

Git-submodules

В проекте с Dockerfile может ничего кроме Dockerfile не быть. Но иногда необходимо при сборке образа поместить в него какие-то дополнительные артефакты, например: скрипты.

Но иногда возникает потребность засунуть в образ целый проект с кучей файлов. И если этот проект располагается на том же GIT-репозитарии, то проще всего это сделать с помощью Git — Submodules.

Механизм сабмодулей позволяет вместо того, чтобы перемещать файлы физически из одного проекта в другой (либо скриптами, либо капипастой), воспользоваться эдаким аналогом символической ссылки, когда в проекте сохраняется метаинформация о директории и о том, что в ней должно лежать с указанием точного адреса ввиде URL другого git-репозитория.

С Git — Submodules всё понятно — они просто работают. Но есть ли поддержка всего этого в Jenkins?

Да!

В разделе Source Code Management → GIT добавьте дополнительное поведение Advanced sub-modules behaviours и поставьте галку как на рисунке.

SCM-GIT_Advanced-sub-modules-behaviours

Готово.

Вычисляемый Docker-image tag

Иногда в настройках Docker Build and Publish плагина в качестве Tag необходимо указать значение, которое невозможно получить простой комбинаций переменных окружения в соответствующем текстовом поле.

Чтобы обойти это ограничение, делаем следующее: В раздел Build добавляем блок с Execute shell, в котором вычисляем значение для нашего TAG и складываем его в файл tmp.properties (да, просто в файл)

jenkins-complex-tag_exec-shell

Далее воспользуемся возможностями Environment Injector Plugin (всё в том же разделе Build). Извлечём новую переменную окружения из только что созданного файла.

jenkins-complex-tag_inject-env-variables

После этого воспользуемся нашим TAG точно так же, как до этого воспользовались GIT_COMMIT.

jenkins-complex-tag_docker-build-and-publish

Готово

 

  • Nik

    Здравствуйте!
    Сделал все по вашему гайду
    но выскакивает ошибка
    Cannot connect to the Docker daemon. Is the docker daemon running on this host?
    Build step ‘Docker Build and Publish’ marked build as failure
    что делать?

    • Viktor Borisov

      Docker не установлен или не запущен.