Установка Jenkins на Ubuntu 24.04 LTS и его настройка для автоматизации разработки
Рассмотрим, как установить Jenkins, и на примере веб-приложения на Java покажем, как автоматизировать процесс сборки и поставки его на веб-сервер Jetty.
Введение
Jenkins — один из популярных инструментов CI/CD. Он существенно облегчает интеграцию разрозненных копий с основной ветвью в репозитории. Кроме того, позволяет автоматизировать сборку проекта и запуск тестов, что значительно ускоряет цикл разработки.
CI/CD ((Continuous Integration / Continuous Delivery) — непрерывные интеграция и доставка ПО — методология, позволяющая команде сосредотачивать усилия в большей степени на воплощении требований, нежели на рутинных задачах поддержания качества кода и системном администрировании.
В соответствии с CI‑частью методологии разработка ведется путем небольших изменений. Такой подход нуждается в частом, практически постоянном тестировании, что требует высокой степени автоматизации.
Поскольку сейчас приходится держать код одновременно в разных средах — например, для разработки, тестирования, коммерческой эксплуатации — возникает необходимость в упрощении процессов встраивания и синхронизации изменений на всех используемых площадках, во всех окружениях. За эту работу отвечает CD‑часть методологии.
В совокупности, отлаженные CI/CD‑процессы ведут к меньшему количеству ошибок, удешевлению продукта и его более высокому качеству.
Jenkins — написанный на Java сервер автоматизации с открытым исходным кодом. После установки набор возможностей Jenkins весьма минималистичен. Однако благодаря расширяемости и многочисленным плагинам, можно подобрать настройки для конкретных нужд, что делает работу с ним комфортной и продуктивной.
В Jenkins используется несколько специфических терминов. Мы будем осваивать их по мере необходимости. В его архитектуре есть две основные роли узлов: контроллер и агенты. В более ранних источниках можно встретить названия master (главный) и slaves (подчиненные). Контроллер — управляющий центр, который занимается планированием и распределение задач агентам, отвечающим за их выполнение.
В статье мы подробно рассмотрим не только установку Jenkins, но и на примере веб-приложения настроим автоматизацию сборки и доставки кода на веб-сервер Jetty с использованием фреймворка для Java‑проектов Maven и репозитория Git. Не обойдем вниманием и особенности работы Jenkins — например, поскольку вся история хранится только в контроллере, то важно правильно задавать ротацию логов.
Преимущества Jenkins
Jenkins — популярный выбор во многих организациях. Помимо своих функциональных возможностей этот инструмент:
- берет на себя множество этапов разработки: сборку, тестирование, развертывание, что значительно сокращает время доставки, а также упрощает и удешевляет рабочие процессы;
- поддерживает множество самых разных технологий, совместим со всеми системами контроля версий, платформами сборки и языками программирования;
- располагает обширной библиотекой плагинов, которые расширяют его функциональность, а также интегрируют с другими инструментами;
- удобен в работе и гибок в настройке, поддерживает как визуальный так и интерфейс командной строки, что радует и начинающих, и опытных пользователей.
- получил широкое распространение и де‑факто стал стандартом для CI/CD, в том числе и благодаря активному развитию — многие компании включили Jenkins в свои рабочие процессы;
- имеет открытый исходный код, что дает тысячам специалистов по всему миру улучшать код и сообщать разработчикам о недочетах;
- собирает вокруг себя большое и активное сообщество, благодаря чему постоянно улучшается, развивается и поддерживается.
Требования
Jenkins скромен в запросах. Ниже указаны минимальные (в скобках — рекомендуемые) значения:
- 256 МБ (4 ГБ) оперативной памяти;
- 1 ГБ дискового пространства для установки в систему, 10 ГБ (50 ГБ) — при работе с Docker.
Разумеется, устанавливающий должен обладать правами администратора для работы с sudo
.
Подготовка инфраструктуры
Устанавливать Jenkins будем на облачную виртуальную машину, развернутую на платформе Selectel.
В панели управления платформой переходим в раздел Облачная платформа > Серверы и нажимаем кнопку Создать сервер.
На следующем экране переходим к конфигурированию заказываемой машины. Операционную систему возьмем Ubuntu 24.04 LTS. Для наших целей достаточно будет единственного vCPU, 1 ГБ оперативной памяти и 5 ГБ дискового пространства.
В разделе Сеть выберем или создадим подсеть с публичным IP‑адресом, чтобы к машине можно было подключаться из интернета. Для доступа можно использовать либо пароль пользователя root, либо SSH-ключ.
Некоторые версии ОС, например Ubuntu 24, требуют доступа исключительно с использованием SSH. В таких случаях поле ввода пароля root в панели управления отключено.
Виртуальная машина создается за несколько минут. Копируем ее IP‑адрес:
Подключаемся с помощью утилиты SSH, указав скопированный IP‑адрес созданного сервера:
ssh root@<IP-адрес>
Если при создании машины для доступа указывался SSH-ключ, то для подключения требуется указать путь к его закрытой части:
ssh -i <файл закрытой части> root@<IP-адрес>
При первом подключении система попросит подтверждение — новый ключ «не известен ни под каким именем»:
ssh -i .ssh/id_rsa root@213.148.12.45
Вывод:
The authenticity of host '213.148.12.45 (213.148.12.45)' can't be established.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '213.148.12.45' (ED25519) to the list of known hosts.
Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.8.0-51-generic x86_64)
Обновим систему на свежеустановленном сервере:
apt-get update && apt-get upgrade
Чтобы обезопасить себя от внезапной нехватки памяти, а также избежать ненужных предупреждений Jenkins, создадим и активируем файла подкачки. С учетом взятого 1 Гб RAM, 1 Гб Swap‑файла будет вполне достаточно:
fallocate -l 1G /swapfile && \
chmod 600 /swapfile && \
mkswap /swapfile
Активируем получившийся файл подкачки, а также обеспечиваем его автоматический запуск при следующем старте сервера:
swapon /swapfile
printf '%s\n' '/swapfile none swap sw 0 0' >> /etc/fstab
Теперь можем установить необходимое ПО.
Установка JDK
Для работы Jenkins и Maven нужна Java, причем для Maven требуется именно JDK:
apt-get install -y openjdk-17-jdk
По завершении установки выполняем проверку:
java -version
Вывод:
openjdk version "17.0.13" 2024-10-15
OpenJDK Runtime Environment (build 17.0.13+11-Ubuntu-2ubuntu124.04)
OpenJDK 64-Bit Server VM (build 17.0.13+11-Ubuntu-2ubuntu124.04, mixed mode, sharing)
Установка Jenkins
Jenkins можно установить тремя способами:
- используя системный менеджер пакетов;
- как контейнер в Docker;
- в виде архива веб‑приложений, WAR (Web application Archive).
Менеджер пакетов
Репозиторий Jenkins не входит в стандартную поставку Debian и Ubuntu, поэтому его надо добавить вручную. Для этого сначала принимаем ключ и обновляем список источников ПО. Пусть вас не смущает появление debian-stable в некоторых URL — менять на Ubuntu эти вхождения не надо:
wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
https://pkg.jenkins.io/debian-stable binary/ | tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
apt-get update
Теперь стандартным способом можно установить, а в дальнейшем и обновлять Jenkins:
apt-get install -y jenkins
Сервис Jenkins запускается автоматически. Проверить его статус можно с помощью команды управление сервисами:
systemctl status jenkins
Вывод:
jenkins.service - Jenkins Continuous Integration Server
Loaded: loaded (/usr/lib/systemd/system/jenkins.service; enabled; preset: enabled)
Active: active (running) since Sat 2024-12-28 14:08:30 UTC; 1min 47s ago
Main PID: 46292 (java)
Tasks: 38 (limit: 1121)
Memory: 381.2M (peak: 439.1M)
CPU: 15.174s
CGroup: /system.slice/jenkins.service
└─46292 /usr/bin/java -Djava.awt.headless=true -jar /usr/share/java/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8080
Как видим, сервис запущен. Если этого не произошло, то в первую очередь следует проверить, свободен ли порт 8080 и хватает ли оперативной памяти.
В будущем придется время от времени перезапускать Jenkins, чтобы изменения, которые мы привнесем вступали в силу. Делать это можно будет командой:
systemctl restart jenkins
Установка через Docker
На всякий случай опишем установку самого Docker. Если он уже присутствует в системе, следующие команды можно пропустить:
apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update && apt-get install -y docker-ce
В любом случае нелишним будет убедиться, что Docker запущен:
systemctl status docker
Образов Jenkins для Docker много. Рекомендуемый официальный образ из репозитория Docker Hub содержит версию с долгосрочной поддержкой и готов к использованию. Однако у него есть и недостаток — отсутствие поддержки Docker CLI и связки с часто используемыми плагинами Blue Ocean. Мы описываем процесс установки, который устраняет указанные ограничения.
Начнем с создания мостовой сети:
docker network create jenkins
Чтобы запускать команды Docker на нодах Jenkins, понадобится образ docker:dind
. Команда ниже, не найдя его локально, подтянет необходимые файлы с library/docker
:
docker run \
--name jenkins-docker \
--rm \
--detach \
--privileged \
--network jenkins \
--network-alias docker \
--env DOCKER_TLS_CERTDIR=/certs \
--volume jenkins-docker-certs:/certs/client \
--volume jenkins-data:/var/jenkins_home \
--publish 2376:2376 \
docker:dind \
--storage-driver overlay2
Названия опций говорят сами за себя. Остановимся подробнее на нескольких моментах:
Имя, в нашем случае jenkins-docker
, — произвольное. Опция ‑‑detach
запускает Docker‑контейнер фоновым процессом — остановить его можно командой:
docker stop jenkins-docker
Перезапуск Jenkins проще всего будет осуществлять перезапуском контейнера:
docker restart jenkins-docker
Запуск наших контейнеров потребует привилегированный доступ. В будущих версиях ядра Linux некоторые ограничения возможно уйдут, но пока используем --privileged
.
Привилегированный запуск контейнеров Docker позволяет им получить расширенные права и доступ к ресурсам хостовой операционной системы. Они получают возможность:
- взаимодействовать с физическим оборудованием — например, с сетевыми интерфейсами или блочными устройствами;
- иметь полный набор возможностей ядра — например, загружать в него модули;
- обходить некоторые ограничения безопасности — поэтому такой режим рекомендуется использовать только тогда, когда это действительно необходимо.
Ключи, начинающиеся с --network
, задают параметры мостовой сети, созданной на предыдущем шаге — название и хост. Так как контейнеры запускаются в привилегированном режиме, то рекомендуется использовать TLS для обмена данными с сервером Docker. Переменная окружения DOCKER_TLS_CERTDIR
хранит путь к корневому каталогу с сертификатами для работы с Docker.
Для запуска привилегированного контейнера требуется наличие общего тома. Опция --volume
сопоставляет имена Docker и объекты файловой системы.
Далее создаем Docker‑файл с произвольным именем — например, my‑jenkins
:
nano my‑jenkins
Содержание Docker‑файла следующее:
FROM jenkins/jenkins:2.491-jdk17
USER root
RUN apt-get update && apt-get install -y lsb-release
RUN curl -fsSLo /usr/share/keyrings/docker-archive-keyring.asc \
https://download.docker.com/linux/debian/gpg
RUN echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/docker-archive-keyring.asc] \
https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
RUN apt-get update && apt-get install -y docker-ce-cli
USER jenkins
RUN jenkins-plugin-cli --plugins "blueocean docker-workflow"
Строим образ, задав ему описательное имя — например, jenkins-blueocean:2.491
. Обратите внимания на точку в конце — текущий каталог будет использоваться в качестве контекста для сборки:
docker build -f my‑jenkins -t jenkins-blueocean:2.491 .
Запускаем созданный контейнер:
docker run \
--name jenkins-blueocean \
--restart=on-failure \
--detach \
--network jenkins \
--env DOCKER_HOST=tcp://docker:2376 \
--env DOCKER_CERT_PATH=/certs/client \
--env DOCKER_TLS_VERIFY=1 \
--publish 8080:8080 \
--publish 50000:50000 \
--volume jenkins-data:/var/jenkins_home \
--volume jenkins-docker-certs:/certs/client:ro \
myjenkins-blueocean:2.491
Когда задаются порты через двоеточие, то первое значение отвечает за хост, второе — за контейнер.
Если нет взаимодействия с другими контейнерами, то строку --publish 50000:50000
можно убрать. Дополнительная информация — в документации.
Установка через war‑файл
Файл Jenkins Web application ARchive (WAR) опирается на Winstone, обертку контейнера сервлетов Jetty, и может быть запущен на любой операционной системе или платформе с подходящей версией Java.
Получаем WAR‑файл последней версии — 2.491 на момент написания данной статьи. Для этого заходим на страницу загрузок и копируем ссылку:
После чего используем ее в терминале как параметр для скачивания. Имя файла — произвольное, пусть будет jenkins.war
:
wget -O jenkins.war https://get.jenkins.io/war/2.491/jenkins.war
На той же странице копируем контрольную сумму:
Создаем проверочный файл, назовем его, к примеру, check_sum
:
nano check_sum
Содержимое файла — скопированная на сайте контрольная сумма и имя проверяемого файла, разделенные пробелом:
ccef73536436ced77776c994cfc86897d6c3899efe8904def444036663111c9b jenkins.war
Используем созданный файл для подтверждения корректности скачанного war‑архива:
sha256sum -c check_sums
Наконец, открываем терминал и вводим команду:
java -jar jenkins.war &
Добавление амперсанда в конец строки — запуск введенной команды в фоновом режиме, иначе текущий сеанс в терминале будет захвачен. В процессе автоматически будет создан пароль администратора, который можно подсмотреть в /root/.jenkins/secrets/initialAdminPassword
.
Если команда захватывает терминал, то перевести ее выполнение в фоновый режим можно, нажав Ctrl+Z и введя bg
.
Перезапуск Jenkins будем осуществлять следующим образом. Находим запущенный наш процесс, определяем его идентификатор PID (второй столбец данных):
ps aux | grep jenkins.war
Вывод:
root 4064 11.4 27.6 2371424 272016 pts/0 Sl 12:58 0:13 java -jar jenkins.war
root 4147 0.0 0.2 7088 2048 pts/0 S+ 13:00 0:00 grep --color=auto jenkins.war
После чего посылаем сигнал на завершение:
kill 4064
Как изменить порт подключения Jenkins
В рассматриваемых примерах Jenkins использует порт 8080 — его номер задан по умолчанию. Если порт занят и используется другими сервисами, можно его перенастроить для избежания конфликта.
Чтобы Jenkins подключался к другому порту, в файле /etc/default/jenkins
нужно изменить значение переменной HTTP_PORT
на желаемый порт и перезапустить сервис Jenkins.
# port for HTTP connector (default 8080; disable with -1)
HTTP_PORT=8081
Обратите внимание, подойдет не каждый порт. Jenkins запускается не от имени root
— у него нет прав слушать порты до 1024. Лучший способ решить проблему конфликта портов — оставить Jenkins работать на 8080‑ом и настроить переадресацию трафика с помощью iptables
.
Настройка Jenkins
Все готово. Можно переходить к настройке. В Jenkins управление осуществляется с помощью веб‑интерфейса, который по умолчанию доступен на порту 8080. Открываем браузер и в адресную строку вводим http: //<IP-адрес сервера>: 8080
:
Интерфейс может не появиться по причине закрытости порта 8080 или неактивного состояния самого Jenkins.
Строго говоря, за работу веб‑интерфейса отвечает Jetty — встроенный веб‑сервер для обработки HTTP‑запросов.
Когда Jenkins запускается, он поднимается на сервере Jetty — это позволяет ему функционировать как веб-приложение, предоставляя доступ к интерфейсу через веб-браузер. Jetty обрабатывает все запросы к Jenkins, поступающие от самых разных источников: графического интерфейса, API, различных действий, плагинов и т. п. Такой подход — использование встроенного сервера — делает Jenkins более удобным для развертывания, поскольку снимает необходимость устанавливать и настраивать отдельный веб-сервер.
Для продолжения настройки потребуется ввести пароль администратора Jenkins, который хранится в файле /var/lib/jenkins/secrets/initialAdminPassword
. Посмотреть и скопировать нужное место файла можно разными способами, например выведя его содержимое на экран:
cat /var/lib/jenkins/secrets/initialAdminPassword
Копируем пароль, вставляем его в поле ввода и нажимаем Продолжить.
Установка плагинов
На следующем шаге потребуется выбрать режим установки плагинов Jenkins. Воспользуемся Install suggested plugins — получить все предлагаемые плагины:
Процесс установки плагинов займет какое‑то время.
Конфигурирование Jenkins
По завершении установки всех предложенных плагинов, создаем профиль администратора:
На следующем экране Jenkins попросит проверить и подтвердить публичный адрес сервера:
Нажимаем Продолжить. Появится сообщение о готовности Jenkins к работе:
На этом основная настройка Jenkins закончена. Запускаем его, нажав Start using Jenkins. Откроется рабочая панель:
Установка Git
Git понадобится для клонирования репозитория с исходным кодом на нашу машину. Установка предельно проста:
apt-get install -y git
Установка Maven
Устанавливаем Maven:
apt-get install -y maven
Узнать версию Maven можно стандартным способом:
mvn --version
Вывод:
Apache Maven 3.8.7
Maven home: /usr/share/maven
Java version: 17.0.13, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: en, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-51-generic", arch: "amd64", family: "unix"
Значение Maven home нам еще понадобится для дальнейшей настройки Jenkins.
Настройка Maven в Jenkins
Jenkins не всегда распознает установленный в системе Maven, нужно быть готовым указать его явно. Выбираем Настроить Jenkins в левом меню:
С некоторых пор в Jenkins появился дополнительный уровень безопасности — выполнение сборок на стороннем узле. Воспользуемся предложением использовать распределенные сборки.
Нажимаем Настроить агент и придумываем имя для узла:
Потребуется указать каталог для файлов агента. Создадим его в терминале:
mkdir -p /var/local/jenkins/agents/smith
Теперь возвращаемся к браузеру, нажимаем кнопку Создать и переходим к странице настроек агента, где вводим путь к созданной директории:
Ниже выбираем для оставшихся параметров другие подходящие значения. Почти все оставляем по умолчанию, измененные отмечены зеленой обводкой:
На основном узле блокируем возможность сборок установкой количества исполнителей равным нулю:

Возвращаемся на главную страницу Dashboard, выбираем Настроить Jenkins, после чего переходим к Tools — конфигурации глобальных инструментов:
В появившемся окне в верхней части настройки оставляем по умолчанию.
Прокручиваем вниз, ищем раздел Maven и нажимаем кнопку Добавить Maven.
Снимаем флажок Установить автоматически, после чего открывается два поля ввода. Даем установке произвольное имя — например, Maven для ясности. Путь к домашней папке Maven — /usr/share/maven
.
Сохраняем настройки и перезапускаем Jenkins, чтобы изменения вступили в силу. Способы перезапуска различаются — выше мы их описали для каждой схемы установки. После возобновления работы Jenkins может потребоваться ввести имя администратора и пароль.
Создание автоматической сборки
Добавление учетных данных
На одном из следующих шагов мы будем подключать Git. Если репозиторий приватный, то заранее надо позаботиться о параметрах доступа. Для этого в настройках выбираем Credentials.
Credentials — учетные данные для доступа к внешним сайтам и приложениям, которые могут взаимодействовать с Jenkins: репозитории; облачные системы хранения, сервисы, базы данных. Такая технология и безопаснее, и удобнее, чем жесткое кодирование имени пользователя и пароля где‑то в скриптах.
В открывшемся окне надо проследить,чтобы задавался правильный способ входа — например, по имени пользователя и паролю. Далее всё, что надо сделать — ввести необходимые данные в соответствующие поля. В поле Description добавляем произвольное описание для подсказки.
Завершаем создание учетных данных, нажав на кнопку Create.
Добавление проекта
Возвращаемся на главную страницу и выбираем Создать Item:
Далее придумываем название проекта — пусть это будет Lollipop. После чего нажимаем на кнопку Создать задачу со свободной конфигурацией, а затем OК внизу страницы.
На вкладке General находим раздел Управление исходным кодом и выбираем Git. Система предлагает ввести URL Git репозитория:
Если репозиторий приватный, то появится ошибка об отсутствии доступа. В таком случае переходим в раздел Credentials и выбираем из выпадающего списка Jenkins:
В появившемся окне вводим Username и Password:
Из выпадающего списка Credentials выбираем нужное имя пользователя:
Ошибка доступа больше не возникает:
После указания репозитория исходного кода, настраиваем сборку. Находим раздел Сборка, нажимаем Добавить шаг сборки и выбираем из выпадающего списка Вызвать цели Maven верхнего уровня.
Выбираем нашу настройку Maven и в поле Цели вставляем команду для сборки maven-проекта:
clean install -P production
Результат сборки будет сохраняться в директории /var/lib/jenkins/workspace/Lolipop/target/
. В нашем примере это будет готовый к развертыванию war-файл. (Напоминаю, Lolipop — название нашего проекта).
Посмотрим, каким образом автоматизировать процесс развертывания war-файла на веб-сервере Jetty, Для простоты используем ту же машину.
Подробнее о Jetty и его установке рассказывается на официальнос сайте.
Добавим еще один шаг сборки, на котором war-файл копируется в папку /opt/jetty/webapps/
и перезапускается. На этот раз выбираем из выпадающего списка «Выполнить команду shell».
cp -f '/var/lib/jenkins/workspace/Lolipop/target/api.war' '/opt/jetty/webapps/' && systemctl restart jetty
На этом настройка сборки закончена. Нажимаем Сохранить и переходим к запуску.
Запуск сборки
Для запуска сборки выбираем в меню Собрать сейчас. В левом нижнем углу, в разделе История сборок, появляется индикатор процесса с датой и временем запуска:
Во время сборки Jetty последовательно выполнит следующие задачи:
- из репозитория Git получит исходный код проекта последней версии;
- запустит сборку загруженного проекта Maven;
- разместит результаты сборки в папке workspace;
- скопирует war-файл в каталог
/opt/jetty/webapps/
; - перезепустит Jetty.
Маркер зеленого цвета свидетельствует об успешности сборки — в противном случае он будет красный.
Нажав на номер сборки и перейдя в левом меню в раздел Console Output, можно отследить отладочный вывод сборки:
Автоматическая сборка и доставка на веб-сервер настроена. Теперь в нужный момент весь процесс запускается кнопкой Собрать сейчас.
Бывает, что серверов несколько, у всех своя конфигурация. Действуя аналогично, можно для каждого из них создать собственный вариант сборки и перезапуска.
Заключение
Jenkins поддерживает технологии для работы с разными системами контроля версий, включая Git, CVS, Subversion, Clearcase и Mercurial, может собирать проекты на Ant, Maven и Gradle, а также исполнять команды Windows, shell-скрипты и отправлять уведомления о состоянии сборки в автоматическом режиме.
Благодаря такому разнообразному инструментарию, Jenkins можно применять на проектах с разными технологиями и любой сложности. Jenkins также поддерживает триггеры сборки, которые могут срабатывать по определенному расписанию или событию.
Все эти преимущества делают Jenkins незаменимым инструментом при построении процесса разработки.