Построение CI/CD Pipeline для автоматизации тестирования и деплоя в Jenkins. Сбор артефактов и уведомления по электронной почте.
- 00:01:05 Создание Jenkinsfile
- 00:04:41 Добавление GitHub-репозитория в Jenkins
- 00:11:42 Просмотр multibranch-проекта
- 00:13:37 Вывод временных меток в логах
- 00:16:30 Валидация Jenkinsfile
- 00:18:02 Переменная окружения CI
- 00:19:39 Доработка docker-compose pull
- 00:20:43 Команды init и down c защитой в post
- 00:22:33 Первый и повторный запуск
- 00:26:01 Установка git и make на машину-агент
- 00:27:00 Сравнение производительности
- 00:28:25 Этап valid
- 00:28:53 Параллельный запуск линтеров
- 00:31:36 Анализаторы и тесты
- 00:32:44 Переменная REGISTRY для реестра
- 00:36:14 Генерация тегов с номером сборки
- 00:41:13 Сборка production образов
- 00:42:13 Запуск Smoke и E2E тестов
- 00:43:08 Оптимизация числа потоков
- 00:46:01 Аутентификация в Docker-реестре и push
- 00:49:55 Автодеплой на production-сервер
- 00:54:46 Имя пользователя для деплоя
- 00:55:31 Отключение интерактивной SSH-проверки
- 00:56:19 Генерация SSH-ключа для деплоя
- 01:04:14 Подключение через плагин SSH Agent
- 01:06:58 Работа со Staging-сервером
- 01:09:14 Сохранение артефактов
- 01:14:38 Добавление Email-уведомлений
Скрытый контент (код, слайды, ...) для подписчиков.
Открыть →Чтобы не пропускать новые эпизоды подпишитесь на наш канал @deworkerpro в Telegram
чудотворный урок, спасибо.
Спасибо! Стараемся.
Спасибо, большое тебе Дима, ты конечно мастер. А сколько времени уходит если не секрет, что бы все скрипты заработали? Ведь на поиск правильно работающего в данной конфигурации рецепта, может уйти куча времени, иногда с виду простая вещь может упереться так, что мама не горюй, записал бы может стрим какой отдельно, как что то сложное настраивал, было бы тоже весьма познавательно.
С GitHub Actions просидел так три дня. В итоге и запись видео заняла шесть часов, так как каждый прогон Pipeline шёл несколько минут и в случае ошибок после каждого исправления приходилось всё перезапускать.
Понятно, ещё раз спасибо за труд, аналогов таким урокам не видел, там рецепты почти на все случаи жизни собраны, хоть понятно куда копать теперь.
Дмитрий, спасибо большое за урок! Вопрос, будет ли рассмотрен вариант использоваться докер образа с Git lab или вообще Git lab как инструмента? Там же есть встроенная возможность и репозиторий для docker организовать и ci\cd настраивать...
Да, скоро рассмотрим.
Огромное спасибо за труд.
А сколько всего планируется уроков?
Сколько получится. Плюс некоторые добавляются по просьбам из комментариев.
Спасибо!
Этот урок просто бесценный, спасибо
А что если надо сделать деплой на две разных машины? Ну т.е. чтобы было 2 копии сайта. Как это сконфигурировать?
Для этого вместо Docker Compose мы в следующих эпизодах будем использовать Docker Swarm. И он уже задеплоит проект на все подключенные серверы.
А что если у нас есть shared данные. Например, изображения загруженные пользователями. Понятное дело, что можно заиметь ftp сервер какой-нибудь и грузить все туда. Но если все таки без сервера, т.е. хранить изображения надо где-то в отдельной папке, то как тогда ее монтировать в контейнер? Причем надо не забывать, что у нас может быть staging (или даже несколько staging).
Обычно их помещают на отдельный файловый сервер по S3 или FTP.
А если без него, то просто монтируем папку public/upload через volume. И для тестов отдельной командой вроде:
заполняем тестовыми данными.
А почему в Jenkinsfile для make deploy мы явно указываем BUILD_NUMBER=${env.BUILD_NUMBER} make deploy? Ведь остальные переменные по типу HOST мы же не указываем....
В принципе да. Если имя переменной совпадает, то можно не присваивать повторно и работать сразу с
${BUILD_NUMBER}
безenv.
Замечательный урок. Спасибо.
Остался только один вопрос как сделать возможность автоматического отката к прошлой рабочей версии или как сделать возможность хранить на сервере файлы допустим только 4-х или пяти предыдущих деплоев что бы откатить вручную и при этом не забивать дисковое пространство?
Например, в
Prod
объявить подсекциюpost { failure { ... } }
по аналогии со сбором артефактов и там вызвать командуmake auto-rollback
, которая выполнит перезапуск из прошлой рабочей папки по симлинкуcd site && docker-compose up ...
В папке деплоя у нас хранятся только два файла на ~5 КБ. Тысяча таких папок займёт всего 5 МБ.
Спасибо за ответ. Я немного не верно задал вопрос. У меня есть продакшен на котором после деплоя выполняется еще мануальное тестирование и если я нахажу там критические баги то надо откатить продакшен до предыдущей версии. но т.к. мы не используем теги для деплоя мы не можем просто взять и задеплоить предыдущий релиз. Нужен какой то способ запустить деплой предыдущего смерженого пулл реквест.
Так же под файлами деплоя я имелл ввиду не файлы логов а файлы проекта я не использую билд образов и не пушу эти образы в реджестри а просто пулю ветку мастер на сервере и перезапускаю докер композ и была идея просто каждый релиз делать в отдельную папку с номером билда но остается проблема с местом на диске т.к. весь проект знимает прилично места и хотелось бы как то удалять все папки релизов кроме последних 4-х
Тогда можно поробовать деплоить через Deployer или Capistrano. Они как раз будут оставлять только нужное число папок.
При сборке не находится sshagent java.lang.NoSuchMethodError: No such DSL method 'sshagent' found among steps Потом все таки досмотрел видео, когда установил модуль сам)
Дима помоги, у меня проблема: в момент docker-build в production/Dockerfile есть строчка COPY out/buildServer/stats.json app/out/buildServer/stats.json
файл stats.json - это результат работы stats-webpack-plugin, и он обязательно появляется, но не успевает появиться до момента COPY
как дождаться либо здесь, внутри Dockerfile, или в Makefile?
первое что на ум приходит
в Makefile использовать перед билдом контейнеров
но интересно есть ли подобное решение внутри Dockerfile?
Внутри нет. Сборка производится в копии нашей папки, отправленной демону. Там файл не появится.
Дмитрий, добрый день! Во время деплоя jenkins при сборке образа на основе jenkinsci/blueocean не устанавливается docker-compose. Ошибка во время компиляции "Could not build wheels for pynacl which use PEP 517 and cannot be installed directly". Не подскажите, в чем может быть проблема?
Увы, но не подскажу.
RUN apk add --no-cache py-pip musl-dev python3-dev libffi-dev openssl-dev gcc libc-dev rust cargo \
И еще одна проблема (уже после установки docker-compose через curl). Во время запуска пайплайна на стадии "Init" возникает ошибка:
console output
Не подскажите, в чем может быть проблема?
Возможно, что текущему пользователю и файлу docker-compose не проставлена группа docker.
Проблема была с образом jenkinsci/blueocean. Попробовал более ранний образ. Команда make перестала выдавать ошибку только со сборкой на основе jenkinsci/blueocean:1.24.7. А до этого ошибка была и из-под пользователя jenkins (который по умолчанию) и из-под root.
Я также попробовал более старый образ, но на локалке контейнер jenkins у меня падает с ошибкой:
java.io.FileNotFoundException: /var/jenkins_home/war/WEB-INF/lib/cli-2.289.1.jar (Permission denied)
У тебя сразу заработало или еще что-то надо было проставить?
У меня ошибка была именно на проде, на локалке все было нормально. Дополнительно ничего не делал, только образ сменил на 1.24.7. Возможно, ошибка из-за
Можно найти нужный вольюм (docker volume ls) и удалить (docker volume rm volume_name), чтобы он пересоздался при рестарте docker-compose. Но тогда слетят настройки jenkins (доступ к репозиторию, пароли ключи и т.д.), будет полностью переустановленный jenkins. Возможно, потребуется пересобрать сам образ на основе jenkinsci/blueocean
Спасибо за ответ. Настройки не проблема восстановить, так как я уже устанавливал и настраивал его на разные сервера. Рука и голова набиты:))
Добрый вечер, Дмитрий.
При выполнении шага "make init" возникают такие ошибки:
Если выполнить curl запрос к этим адресам, или перейти в браузере, то в ответ получаю следующее сообщение:
Как победить данную проблему?
Добавил для jenkins playbook docker-login
Предыдущая ошибка ушла, но появилась новая, ругается на docker.dind
В обшем ничего не получилось)))
Рекомендации из интернета не помогли, пробовал увеличить лимит по выполнению сборки через COMPOSE_HTTP_TIMEOUT: 120 и DOCKER_CLIENT_TIMEOUT: 120, все сборки завершались ошибкой
Взял ещё один свой проект, там поменьше сервисов собирается в docker-compose-prod.yml
Первая сборка прошла успешно, а вот вторая вывалилась всё с теме же ошибками:
Всё-таки, из-за чего это зависит и как это победить?
Может сервисы отваливаются из-за недостатка памяти. Увеличьте размер виртуальной машины.
Думал об этом, но проблема оказалась совершенно в другом.
Эти ошибки возникали при попытке dind-ом создать контейнеры. Но в самом коде были проблемы, на уровне php, поэтому dind не мог создать контейнер и не отвечал jenkins-у.
Плохо, что не очень информативные ошибки в логах jenkins. Пытался в лохаг dind смотреть, тоже, ничего не находил.
Например как ошибки выше, еле докумекал и то, пока не увидел в инете сообщение, что не только недостаток памяти или плохая скорость инета может влиять.
Хотя вот эта ошибка выскочила тогда, когда с двух веток jenkins пытался одновременно сделать сборку. Тут, я думаю, уже мощности не хватило.
Одновременно на одной виртуалке лучше не запускать. Выставить максимальное число 1.
Только что проверил, моя ошибка, было выставлено "2". Переустанавливал виртуалку и забыл изменить этот параметр.
Добрый день.
Если выставить в настройка jenkins-a число 1 для обрабатываемых задач и при этом сделать подряд два commit-a, то всё равно запускается две задачи.
Можно это как-то победить?
Если стоит 1, то вторая задача будет ждать в очереди.
Опять же, возвращаясь к слабым виртуальным машинам.
Можно ли как-то освобождать swap по завершению сборки, то есть, дописать в Jenkinsfile соответствующую команду? И будет ли это эфективно для слабых машин?
В этом нет смысла.
А у меня такая проблема. Jenkins сканирует github репозиторий раз в минуту и смотрит есть ли изменения. Но бывает, что он запускает пайплан даже если изменений никаких не было. И происходит это не систематизировано, может днем запустить, может ночью. Может неделю все тихо быть, а потом бац - билд пошел. Не сталкивались с таким?
Сталкивался. Но проблемы в этом не вижу.
добрый день! пушу в master, но почему то jenkins игнорирует эту стадию. в логах: Stage "Push" skipped due to when conditional. может надо прописать branch 'origin/master'?
GIT_BRANCH=origin/master
почему то был указан гит и одна ветка, изменил конфигурацию проекта и ветки стали отображаться
Добрый вечер, Дмитрий.
Столкнулся с проблемой на самом первом этапе сборки в jenkins "Declarative: Checkout SCM".
Вываливалась ошибка
И далее в логе
Проблема с правами доступа, как я понял.
Например, на директорию node_modules права drwxr-sr-x 738 root jenkins
И начались эти проблемы после простоя около двух месяцев, в этот промежуток времени ничего не делалось в проекте и не выгружалось.
Проблему решил путём очистки директории проекта в volume /var/jenkins_home/workspace/Project_dev
Но, как я понимаю, это временное решение.
Из-за чего могла случиться такая ситуация, как правильно решать подобные проблемы?
Именно из-за того, что Jenkins запущен от пользователя jenkins, а контейнер node-cli внутри запускается от root. Поэтому Jenkins не может удалить папку node_modules.
Решается либо ручным удалением папки проекта из
workspace
в/var/lib/docker/volumes/jenkins_data/_data/workspace
.Либо в Dockerfile у node-cli можно переключить пользователя:
Либо не обращать внимания и удалять вручную, так как эта проблема встречается редко.
Такая же ситуация с директориями var, vendor и файлом .ready.
До этой проблемы более 20-ти сборок прошли успешно, workspace проекта очищался успешно, а в последних вдруг перестало работать.
Остальные файлы проекта создаются от jenkins.
Добавить нужно не только USER node, как я понимаю?
А зачем его очищать перед каждой сборкой? Это только замедляет выполнение pipeline, не принося особой пользы.
Вот это мне и непонятно)))
Пока вручную не очистил сборка завершалась ошибкой на самом начальном этапе.
Почему до этого всё работало, а потом вдруг перестало?
Видимо он почему-то захотел удалить папку из workspace.
Чаще с ним бывает то, что рядом с workspace/project он создаёт project-2. Тогда тоже желательно workspace вычистить.
Нет, второй директории не было.
Я вчера искал информацию, но то что я нашёл, всё было связано с ручным изменением прав на директорию workspace проекта.
Поэтому очистил директорию проекта, но саму директорию /var/jenkins_home/workspace/Project_dev оставил без изменений.
В workspace проекта при новой сборке файле перезаписываются?
Значит до возникновения ошибки права были установлены такие же
drwxr-sr-x 738 root jenkins на var, vendor, node_modules, public/build.
Сейчас запустил ещё раз сборку, начальный этап "Declarative: Checkout SCM" прошёл успешно, права на указанные директории такие же drwxr-sr-x 738 root jenkins.
Может быть из-за того, что в течении двух месяцев не запускались сборки и что-то не так сохранилось в cache jenkins?
Возможно, что после какого-то перерыва он вычищает workspace. У меня сборки идут каждый день без, поэтому такого не случалось.
В том то и дело, что директория была с файлами от старых сборок.
Вернее некоторые файлы были удалены из workspace проекта, а директории var, vendor, public/node_modules остались, jenkins не смог их удалить.
Если создавать отдельного пользователя для node, то и для composer так же надо создать.
Или достаточно будет создать одного пользователя и для node и для composer?
Для php-cli мы в 59-ом эпизоде создали пользователя app с тем же идентификатором 1000, как у node и jenkins. И команду ready тогда можно будет запускать из php-cli как:
Но всё равно проблемы останутся с правами на файлы в var от php-fpm, у которого встроенный пользователь www-data создан с идентификатором 82 вместо 1000. Можно попробовать заменить его идентификатор через команды
groupmod
иusermod
в Dockerfile.Этот момент я не реализовывал в своём проекте, пока не было необходимости.
Теперь пришло время.
Но всё-таки остаётся загадкой, почему вдруг jenkins решил, что ему не хватает прав.
Возможно из-за версии самого jenkins на сервере?
Если за это время обновляли Jenkins, то может из-за этого он вдруг решил удалить старый workspace.
Не обновлял.
Сейчас использую jenkins/blueocean1.24.7
При обновлении не слетят настройки pipelines?
Не слетят.
Благодарю.
Оказывается слетает всё)))
Обновил с enkinsci/blueocean:1.24.7 до enkinsci/blueocean:1.25.2 и в результате получил ошибку в браузере.
В логах
Посмотрел внимательней лог ошибок контейнера jenkins.
Много ошибок при попытке загрузить плагины.
Пример
Как можно решить подобную проблему?
В сети рекомендуют попробовать удалить содержимое директории /var/jenkins_home/plugins, но тогда, как я понимаю, слетят все настройки.
Перед обновлением образа jenkins делал обновление пакетов через ansible,
В общем непонятная штука получилась.
Для проверки создал ещё одну виртуалку, где пытался воспроизвести проблему, ни так и не смог.
В общем удалил в контейнере директорию /var/jenkins_home/plugins и смог запустить jenkins c новой версией 1.25.2
И ещё вопрос.
Когда заглянул в volume jenkins-a, то увидел директорию проекта, который давно удалён из pipeline, никаких images от него не осталось.
Должны ли из volume автоматически удаляться проекты из /var/jenkins_home при удалении проекта из pipeline?
Вроде остаются.
Можно ли как-то настроить автоматическое удаление ненужных директорий?
Не смотрел.
Добрый день, подскажите как бороться с переполнением диска в jenkins.
docker system prune -af --filter until=240h не помогает.
Запуск в ручную docker system prune -a - выдает Total reclaimed space: 0B. overlay2 - 57Gb.
Чистить внутренний докер, а не только внешний:
Благодарю.
Спасибо за урок! Не понимаю как запускать деплой повторно. Первый прошел успешно, все контейнеры поднялись, сайт запускается. При следующих деплоях вываливается ошибка, что порт уже занят и контейнер nginx не поднимается.
Что я делаю не так? Это конечно решится добавлением docker-compose down перед build прошлой версии сборки, но у вас я этого не вижу. Или вы ручками на сервере запускаете docker-compose down а потом деплоите?
И еще второй вопрос как быть с volume для postgres? Каждый раз после деплоя создается новый volume с новой версией , и соответсвтенно пустой контент на сайте после деплоя. Например было название volume site_253_manager-postgres стал site_254_manager-postgres.
Сам разобрался. Для этого в папку, где лежит docker-compsoe.yml нужно положить env COMPOSE_PROJECT_NAME=name , где name указать алиас, который будет добавляться ко всем названиям контейнеров volume и тд. Тогда не важно как будет называться папка, со всех будет запускаться как один проект.
На локальной машине под MacOS в Jenkins все шаги нормально проходят, на виртуальном сервере тесты smoke и e2e падают.
Пробовал менять таймаут, не помогает. Гуглил вроде как браузер не запускается перед тестом. Кто может помочь?
Все таки дело было в тайм ауте(((
Дмитрий, в этом уроке Вы используете githab.com для хранения репозиториев. И в интерфейсе есть тесная интеграция с github. Для gitlab таковой нет, и даже плагин (согласно https://docs.gitlab.com/ee/integration/jenkins.html) не помогает настроить функционал из урока.
А у меня код храниться на gitlab.com.
Есть ли способы подстроиться под gitlab.com для задач этого урока? Или разумнее перевезти код на github?
Спасибо!
Или войти через: