Практика CI/CD широко распространена в современном мире и представить ручной деплой у FAANG с их бесчисленными ежедневными изменениями просто невозможно. То же будет справедливо и для продуктовых компаний: десятки ручных деплоев в день вытянуть можно, но это потребует колоссальных ресурсов.

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

Предпосылки и подготовительные работы

На этом этапе у вас уже должен быть установлен Docker for Windows, с настройкой под Linux-контейнеры и включен WSL 2 в Windows Features. Либо Linux/macOS с установленным Docker. Гайдов как это настроить достаточно много и найти их не сложно, поэтому первичная настройка Docker и WSL в этой статье описана не будет. У меня установлен Docker for Windows версии 4.10.1 и установлена WSL Ubuntu 20.04 LTS.

Отдельным абзацем отмечу, что из контейнера с Jenkins потребуется доступ к Docker daemon в котором запущен этот Jenkins контейнер. Нужно это, чтобы Jenkins мог создавать контейнеры в которых будет происходить сборка образов, так как весь процесс будет работать на одной машине. Работать это будет следующим образом: Jenkins ловит триггер по которому начинается сборка и обращается к Docker daemon в котором он сам запущен и рядом создает еще один контейнер в котором собирает Docker образ - по завершению сборки такой контейнер удалится. Для этого в настройках Docker включите следующую функцию:

Настройка находится на вкладке General
Настройка находится на вкладке General

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

Для самых продвинутых

Все основные образы, контейнеры и тома я определили в docker-compose.yml, возможно он упростит запуск тестового стенда и вам, но некоторые настройки внутри Jenkins и Nexus все же придется взять из следующих шагов:

docker-compose.yml
services:
  jenkins:
    image: jenkins/jenkins:lts-jdk11
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    user: root
    networks:
      - cicd_network

  nexus:
    image: sonatype/nexus3
    ports:
      - "8081:8081"
      - "8083:8083"
    volumes:
      - nexus_data:/nexus-data
    networks:
      - cicd_network

volumes:
  jenkins_home:
    external: true
    name: jenkins_home
  nexus_data:
    external: true
    name: nexus_data

networks:
    cicd_network:
        driver: bridge

Создадим тома

Для начала выполните в PowerShell следующие команды для создания томов:

docker volume create --name jenkins_home
docker volume create --name nexus_data

Эти тома будут хранить данные от контейнеров чтобы при повторном запуске не приходилось заново настраивать Jenkins и Nexus. Контейнеры способны сами создать необходимые тома, но я предпочитаю делать это заранее для пользования docker-compose.

Запуск и настройка Jenkins

Сначала запустим Jenkins и проинициализируем его. Для этого в PowerShell выполните следующую команду:

	docker run -d `
  --name jenkins `
  --user root `
  -p 8080:8080 `
  -p 50000:50000 `
  -v jenkins_home:/var/jenkins_home `
  -v /var/run/docker.sock:/var/run/docker.sock `
  jenkins/jenkins:lts-jdk11

Особо внимательные наверняка заметили, что контейнер выполняется с правами root пользователя и монтирует Unix socket. Увы это вынужденная мера чтобы контейнер смог обратиться к Docker daemon. Подробнее об этом описано в статье Docker Tips : about /var/run/docker.sock

Далее Docker попытается скачать образ jenkins/jenkins:lts-jdk11 и запустить контейнер. Если в предыдущей команде не получилось скачать образ, то выполните в PowerShell следующую команду:

docker pull jenkins/jenkins:lts-jdk11

Если все получилось, то в консоль будет выведен Id контейнера, а по адресу localhost:8080 вы увидите окно с инициализацией Jenkins:

Как вы догадались, пароль можно посмотреть по указанному выше пути, а еще зайти в консоль вывода контейнера и найти следующие строки:

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

ac8c9a1e554e4f448d46f5cdcc94477d

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

Далее выберите "Install suggested plugins" и дождитесь окончания установки. Увы, но на этом этапе мастер установки не даст выбрать плагины для работы с Docker - что иронично, интернет для их скачивания в контейнере есть, а вот поискать плагины заранее нельзя. Хотя это обходится с помощью Dockerfile для запуска Jenkins контейнера - примет вот тут.

Когда настройка завершится, будет предложено создать пользователя. Как закончите, зайдите в настройки Jenkins и перейдите в Plugin manager - там нужно установить 3 плагина:

  1. Blue Ocean - у меня версия 1.25.5

  2. Docker Pipeline - у меня версия 1.29

  3. Docker plugin - у меня версия 1.2.9

Необходимые зависимости подтянутся во время установки, а по её окончанию перезапустите контейнер. Операцию можно считать успешной если после всех действий слева на главном экране появилась кнопка "Open Blue Ocean" и по её нажатию открывается окно плагина.

Теперь попробуем подключиться к Docker daemon. Для этого снова перейдите в настройки и выберите "Manage Nodes and Clouds", затем "Configure Clouds" и "Add a new cloud" - "Docker".

Тут нажмите на "Docker Cloud details" - появится несколько полей и их нужно заполнить следующими значениями:

  1. Name - "docker"

  2. Docker host URI - "tcp://host.docker.internal:2375" - еще можно попробовать "unix://var/run/docker.sock" и "tcp://172.17.0.1:2375", но у меня сработал только первый

  3. Отметьте чекбоксы "Enabled" и "Expose DOCKER_HOST"

Теперь в этой же секции нажмите "Test connection". Вы поймете что подключится удалось когда слева от кнопки появится версия API:

Далее настроим агентов сборки. Для этого нажмите на "Docker Agent templates" и "Add Docker Template", а поля заполнити следующими значениями:

  1. Labels и Name - "docker-agent"

  2. Docker Image - "benhall/dind-jenkins-agent:v2" - если поискать, то можно найти и другие образы для использования в качестве агента сборки

  3. Connect method - "Connect with SSH"

  4. SSH key - "Inject SSH key"

  5. User - "root"

Остальные поля оставьте как есть и нажмите "Save". На этом базовые настройки Jenkins можно считать завершенными, но мы вернемся к ним на этапе написания пайплайнов.

А теперь займемся Nexus

В целом запуск Nexus мало отличается от запуска Jenkins, так что я просто добавлю сюда PowerShell команду:

docker run -d `
--name nexus `
-p 8081:8081 `
-p 8083:8083 `
-v nexus_data:/nexus-data `
sonatype/nexus3:latest

Разумееется, если на предыдущем этапе снова не получилось скачать образ, то выполните следующую PowerShell команду:

docker pull sonatype/nexus3:latest

Запуск контейнера с Nexus занимает больше времени чем запуск Jenkins - увы красивых картинок с надписью "Подождите" не будет. Тем не мене, как только контейнер запустится, он будет доступен по localhost:8081, а localhost:8083 мы будет использовать для доступа к репозиторию образов Docker. Но сперва завершим настройку Nexus ведь при первом запуске он запросит пароль, который лежит в этом файле в томе nexus_data:

Справа есть кнопка для сохранения этого файла
Справа есть кнопка для сохранения этого файла

Дальше на главной странице Nexus нажмите "Sign in" и для логина admin укажите пароль из этого файла. Далее появится мастер настройки, просто следуйте по его шагам. В мастере будет пункт "Configure Anonymous Access", для себя я выбрал "Configure Anonymous Access".

Теперь по правилам хорошего тона нужно завести учетную запись для Jenkins - по ней он будет авторизоваться в приватном Docker репозитории и пушить образы, но никто не запрещает в домашней версии использовать учетную запись admin.

Для создания пользователя перейдите в настройки Nexus и выберите раздел Users. Затем нажмите "Create local user" и заполните все преложенные поля - для себя я везде ввел "jenkins". Из коробки в Nexus всего 2 преднастроенные роли, так что тут выберите nx-admin.

Теперь создадим репозиторий. Для этого в настройках выберите раздел Repositories и нажмите Create repository. В пресетах выберите "docker (hosted)", имя укажите любое на ваш вкус. На этой же странице отметьте чекбок HTTP и укажите порт 8083 - так по адресу localhost:8083 будет доступен этот репозиторий.

Стоит отметить, что прямо сейчас этот репозиторий работать не будет. Точнее будет, но Docker не сможет в нем авторизоваться. Это решается правкой Realms в одноименной секции настроек. Просто перетащите "Docker Bearer Token Realm" в правый столбец и сохраните изменения - из коробки этот Realm отключен и не зная об этом придется потратить много времени на поиск решения. Теперь Jenkins сможет авторизоваться в Nexus, а у вас успешно выполнится следующая PowerShell команда:

docker login 127.0.0.1:8083 -u jenkins -p jenkins
>> Login Succeeded <<

Переходим к созданию pipeline

Для примера я сделаю пайплайн с типом "Freestyle project" - где просто попытаемся силами Jenkins собрать и запушить Docker образ в Nexus. Этот pipeline будет запускаться по кнопке, хотя можно поэксперементировать и добавить "Multibranch Pipeline", но об этом в другой раз.

Для начала на главной странице Jenkins нажмите "New item" и выберите "Freestyle project", я указал в названии "cicd_test_freestyle". В настройках pipeline нужно будет отметить чекбокс "Restrict where this project can be run" и в поле "Label expression" указать наименование агента для билда - по гайду это "docker-agent", но если вы назвали его как-то иначе, то тут будет выпадающий список с подсказками.

Далее на вкладке "Source Code Management" выберем Git укажем репозиторий из которого будем собирать Docker образ. Я для тестов использовал простенький репозиторий https://github.com/karthi4india/jenkins/ в котором буквально 2 файла: Dockerfile и http сервер.

Для аутентификации в GitHub, если репозиторий приватный, можно сначала зайти в Blue Ocean и оттуда попытаться сделать pipeline - там будет ссылка на GitHub для создания токена с нужными разрешениями. Если этот токен потом вставить в Blue Ocean, то он его запомнит, но Jenkins его не увидит и придется создать Credentials, где логин это ваш логин GitHub, а пароль - это токен.

Далее на вкладке Build в поле Cloud выберем облако "docker", которое настроили в самом начале, а в поле Image добавим 2 записи:

127.0.0.1:8083/cicd_test_freestyle:latest
127.0.0.1:8083/cicd_test_freestyle:${BUILD_NUMBER}

А еще на этой же вкладке нужно будет нажать Advanced и указать там адрес репозитория и Credentials для подключения к нему. Для меня это репозиторий 127.0.0.1:8083

Я опечатался, но вы так не делайте
Я опечатался, но вы так не делайте

Также ниже будет еще одно поле Registry Credentials, там просто укажите Credentials для Nexus. Описывать создание Credentials нет смысла, если их не хватило, то рядом всегда есть кнопка Add, а там все просто.

Так после билда в Nexus будет 2 образа: один с номером билда и второй с тегом latest, а еще сохранятся предыдущие билды:

Теперь сохраните изменения и переходите в созданный проект - он будет на главной странице Jenkins и слева нажмите "Build now". Всплывет подсказка, что билд запланирован и ниже появится агент на котором будет происходить сборка. Агент может появиться не сразу и наверняка появится сообщение "‘Jenkins’ doesn’t have label ‘docker-agent’", но через несколько секунд оно пропадет и начнется сборка Docker образа:

Сборка и контейнер, который поднял Jenkins
Сборка и контейнер, который поднял Jenkins

Самое время нажать на номер билда слева и перейти в Console Output. Если все настроили правильно, то в конце логов будет ждать приятная надпись "Docker Build Done Finished: SUCCESS", а в Nexus появятся 2 Docker образа.

Как итог

CICD на домашнем ПК собрать можно, он будет работать, билдить образы и в целом с этим очень интересно поиграться в такой песочнице. Сюда можно и нужно добавить Multibranch Pipeline для сборки по разным веткам, можно добавить и Kubernetes чтобы собранный Docker образ деплоился в daemon, но об этом уже в другой статье.

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