В современном мире разработки программного обеспечения непрерывная интеграция и доставка (CI/CD) становятся неотъемлемой частью процессов разработки. Jenkins, как один из ведущих инструментов CI/CD, помогает автоматизировать сборку, тестирование и развертывание приложений. Однако настройка и управление Jenkins могут быть трудоемкими и сложными, особенно в крупных проектах со множеством разработчиков и разнообразными требованиями.
Docker, контейнеризация и оркестрация контейнеров пришли на помощь, предлагая более эффективные и масштабируемые решения для развертывания приложений и инфраструктуры. Docker позволяет разработчикам упаковывать приложения и их зависимости в контейнеры, которые можно легко переносить и запускать на любой системе с установленным Docker.
В этой статье мы рассмотрим, как с помощью Docker можно автоматизировать настройку и развертывание Jenkins. Мы пройдем через все этапы — от создания Docker файла и настройки Docker Compose до интеграции Jenkins Configuration as Code (JCasC) для автоматической конфигурации Jenkins. В результате у вас будет полное понимание процесса и готовое решение для автоматизации Jenkins в ваших проектах.
Перед тем как приступить к настройке Jenkins с помощью Docker, необходимо убедиться, что у вас есть все необходимые инструменты и программное обеспечение. В этом разделе мы рассмотрим, что потребуется для успешной автоматизации Jenkins и как установить необходимые компоненты.
Docker можно установить на различных операционных системах, включая Linux, macOS и Windows. Ниже приведены шаги для установки Docker на наиболее популярных платформах
Linux (Ubuntu)
Обновите список пакетов командой:
sudo apt update
Установите пакеты для работы с HTTPS:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
Добавьте официальный GPG-ключ Docker:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Добавьте Docker-репозиторий в APT-источники:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Установите Docker:
sudo apt install docker-ce
Убедитесь, что Docker работает:
sudo systemctl status docker
macOS
Windows
Docker Compose обычно устанавливается вместе с Docker Desktop на macOS и Windows. На Linux требуется отдельная установка:
Скачайте последнюю версию Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep -Po '"tag_name": "\K.*?(?=")')/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Сделайте скачанный файл исполняемым:
sudo chmod +x /usr/local/bin/docker-compose:
Проверьте установку:
docker-compose --version
Docker Hub — это облачный репозиторий, где можно находить и хранить Docker-образы. Официальный Jenkins Docker образ доступен на Docker Hub и предоставляет готовый к использованию Jenkins сервер:
Официальный образ регулярно обновляется и поддерживается сообществом, что гарантирует получение стабильного и безопасного окружения.
cloud
В этой главе мы рассмотрим, как создать Docker файл для Jenkins, который будет использоваться для создания Docker-образа. Мы также обсудим, как добавлять конфигурации и плагины в этот образ для удовлетворения специфическим требованиями вашего проекта
Docker-файл — это текстовый документ, содержащий все команды, которые пользователь может вызвать в командной строке для сборки образа. В каждом Docker-файле используются инструкции для определения шага в процессе сборки образа. Основные команды включают:
FROM
: указывает базовый образ для создания нового образа.RUN
: выполняет команду в контейнере.COPY
или ADD
: копирует файлы или директории в контейнер.CMD
или ENTRYPOINT
: определяет команду, которая будет выполнена при запуске контейнера.Начнем с создания простого Docker-файла для Jenkins. Этот файл будет использовать официальный Jenkins образ в качестве базового и добавлять несколько необходимых плагинов.
FROM jenkins/jenkins:lts
RUN jenkins-plugin-cli --plugins workflow-aggregator git
EXPOSE 8080
EXPOSE 50000
Этот базовый Docker-файл устанавливает два плагина: workflow-aggregator
и git
. Также он открывает порты 8080 (для веб интерфейса) и 50000 (для соединения с агентами Jenkins).
Для более сложных конфигураций мы можем добавить дополнительные шаги в Docker-файл. Например, можно настроить Jenkins для автоматического использования определенного файла конфигурации или добавления скриптов для предварительной настройки.
Пример Docker-файла с расширенной конфигурацией:
jenkins_home
для хранения пользовательских конфигураций.custom_config.xml
внутри новой директории с необходимыми конфигурациями:<?xml version='1.0' encoding='UTF-8'?>
<hudson>
<numExecutors>2</numExecutors>
<mode>NORMAL</mode>
<useSecurity>false</useSecurity>
<disableRememberMe>false</disableRememberMe>
<label></label>
<primaryView>All</primaryView>
<slaveAgentPort>50000</slaveAgentPort>
<securityRealm class='hudson.security.SecurityRealm$None'/>
<authorizationStrategy class='hudson.security.AuthorizationStrategy$Unsecured'/>
</hudson>
Обновите Dockerfile следующим образом:
FROM jenkins/jenkins:lts
RUN jenkins-plugin-cli --plugins workflow-aggregator git docker-workflow
COPY jenkins_home/custom_config.xml /var/jenkins_home/config.xml
COPY scripts/init.groovy.d /usr/share/jenkins/ref/init.groovy.d/
EXPOSE 8080
EXPOSE 50000
В этом примере мы устанавливаем дополнительные плагины, копируем файл пользовательской конфигурации и добавляем скрипты в директорию init.groovy.d
для автоматической инициализации Jenkins при первом запуске.
Docker Compose позволяет описать инфраструктуру вашего приложения в виде кода, используя YAML-файлы. Это упрощает процесс настройки и развертывания, делая его повторяемыми и удобными для управления.
Основные преимущества использования Docker Compose:
Создадим файл docker-compose.yml
для развертывания Jenkins вместе с сопутствующими сервисами, такими как база данных и агент Jenkins.
docker-compose.yml
в директории вашего проекта.version: '3.8'
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins-server
ports:
- "8080:8080"
- "50000:50000"
volumes:
- jenkins_home:/var/jenkins_home
networks:
- jenkins-network
jenkins-agent:
image: jenkins/inbound-agent
container_name: jenkins-agent
environment:
- JENKINS_URL=http://jenkins-server:8080
- JENKINS_AGENT_NAME=agent
- JENKINS_AGENT_WORKDIR=/home/jenkins/agent
volumes:
- agent_workdir:/home/jenkins/agent
depends_on:
- jenkins
networks:
- jenkins-network
volumes:
jenkins_home:
agent_workdir:
networks:
jenkins-network:
Этот файл описывает два сервиса:
jenkins
: сервис, использующий официальный образ Jenkins. Порты 8080 и 50000 проброшены для доступа к веб-интерфейсу Jenkins и соединения с агентами. Директория /var/jenkins_home
монтируется на внешний том jenkins_home
, чтобы сохранять данные между перезапусками контейнера.jenkins-agent
: сервис, использующий образ Jenkins inbound-agent
. Агент подключается к серверу Jenkins через URL, указанный в переменной окружения JENKINS_URL
. Рабочая директория агента монтируется на внешний том agent_workdir
.Теперь, когда файл docker-compose.yml
создан, можно запустить все сервисы с помощью одной команды.
docker-compose.yml
.docker-compose up -d
Флаг -d
запускает контейнеры в фоновом режиме. После выполнения этой команды Docker Compose создаст и запустит контейнеры для всех сервисов, описанных в файле.
Теперь вы можете проверить состояние запущенных контейнеров с помощью команды:
docker-compose ps
Если все прошло успешно, то в выводе окажется только jenkins-server
.
Теперь настроим сервер и создадим агента.
Если вы перейдете по адресу http://localhost:8080/
, то при первом запуске увидите следующее сообщение:
Jenkins запустился корректно и ожидает ввода пароля администратора для начальной настройки. Для получения пароля выполните следующую команду:
docker exec -it jenkins-server cat /var/jenkins_home/secrets/initialAdminPassword
Скопируйте полученный пароль и вставьте в форму на странице «Unlock Jenkins». Откроется новое окно с первоначальной настройкой. Выберите «Install suggested plugins». По окончанию установки заполните форму администратора:
Примите URL по умолчанию и завершите настройку. Перейдите в «Настроить Jenkins» → «Nodes».
Нажмите «New Node», укажите имя для нового узла, например «agent», и выберите «Постоянный агент». Заполните остальные поля, как на скриншоте ниже:
После создания агента у вас откроется окно с командой, которая содержит секрет для подключения агента.
Скопируйте секрет и добавьте его в docker-compose.yml
:
environment:
- JENKINS_URL=http://jenkins-server:8080
- JENKINS_AGENT_NAME=agent
- JENKINS_AGENT_WORKDIR=/home/jenkins/agent
- JENKINS_SECRET=<your-secret-here> # Укажите секрет здесь
Для перезапуска введите команды ниже и убедитесь, что jenkins-agent
запустился:
docker-compose down
docker-compose up -d
Jenkins Configuration as Code (JCasC) — это подход, который позволяет описать всю конфигурацию Jenkins в виде YAML-файла. Это упрощает автоматизацию, поддержание и переносимость настроек Jenkins. В этой главе мы рассмотрим как настроить JCasC для автоматической конфигурации Jenkins при запуске контейнера.
JCasC позволяет описать конфигурацию Jenkins в одном YAML-файле, что дает следующие преимущества:
Для начала создадим файл конфигурации.
jenkins.yaml
в директории вашего проекта.jenkins:
systemMessage: "Welcome to Jenkins configured as code!"
securityRealm:
local:
allowsSignup: false
users:
- id: "admin"
password: "${JENKINS_ADMIN_PASSWORD}"
authorizationStrategy:
loggedInUsersCanDoAnything:
allowAnonymousRead: false
tools:
jdk:
installations:
- name: "OpenJDK 11"
home: "/usr/lib/jvm/java-11-openjdk"
jobs:
- script: >
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building...'
}
}
stage('Test') {
steps {
echo 'Testing...'
}
}
stage('Deploy') {
steps {
echo 'Deploying...'
}
}
}
}
Этот файл конфигурации задает:
systemMessage
. Эта строка будет отображаться на главной странице Jenkins. Оно может быть использовано для информирования пользователей о важной информации или изменениях.securityRealm
. Поле allowsSignup: false
отключает возможность самостоятельной регистрации новых пользователей. Далее определяется один пользователь с id: "admin"
и паролем, заданным переменной среды ${JENKINS_ADMIN_PASSWORD}
.authorizationStrategy
. Политика loggedInUsersCanDoAnything
позволяет авторизованным пользователям выполнять любые действия, при этом allowAnonymousRead: false
запрещает анонимным пользователям доступ к системе.tools
. В данном примере указывается JDK с именем OpenJDK 11
и местоположением /usr/lib/jvm/java-11-openjdk
.jobs
. Этот пайплайн включает три стадии: Build
, Test
и Deploy
, каждая из которых содержит один шаг с выводом соответствующего сообщения в консоль. Теперь необходимо интегрировать наш конфигурационный файл jenkins.yaml
с Docker и Docker Compose, чтобы при запуске контейнера Jenkins автоматически применял эту конфигурацию.
Обновите Dockerfile, чтобы скопировать конфигурационный файл в контейнер и установите плагин JCasC:
FROM jenkins/jenkins:lts
RUN jenkins-plugin-cli --plugins configuration-as-code
COPY jenkins.yaml /var/jenkins_home/jenkins.yaml
EXPOSE 8080
EXPOSE 50000
Обновите docker-compose.yml
, чтобы задать переменные окружения и монтировать файл конфигурации. Для этого в блоке volumes
добавьте следующий код:
- ./jenkins.yaml:/var/jenkins_home/jenkins.yaml
После блока volumes
добавьте новый блок environment
(в случае если вы не задавали его ранее):
environment:
- JENKINS_ADMIN_PASSWORD=admin_password
Постройте новый образ Jenkins с конфигурацией JCasC:
docker-compose build
Запустите контейнеры:
docker-compose up -d
После запуска контейнеров, перейдите в браузер по адресу http://localhost:8080
и войдите в систему с учетной записью администратора. Вы должны увидеть сообщения системы и установленную конфигурацию Jenkins в соответствии с вашим jenkins.yaml
-файлом.
Несколько важных замечаний:
docker-compose.yml
и jenkins.yaml
на первый взгляд могут показаться похожими, но выполняют совершенно разные функции. Файл в Docker Compose описывает сервисы и контейнеры, необходимые для запуска Jenkins и его окружения, в то время как файл в JCasC описывает саму конфигурацию Jenkins, включая установку плагинов, настройку пользователей, безопасность, системные настройки и джобы..yml
и .yaml
— это варианты одного и того же формата файла YAML
. Они взаимозаменяемы и поддерживаются различными инструментами и библиотеками для работы с YAML. Применение того или иного формата во многом зависит от исторических предпочтений сообщества; в документации по Docker вы чаще встретите примеры с расширением .yml
, а в документации по JCasC — с расширением .yaml
.jenkins.yaml
предназначен для описания статической конфигурации и не предназначен для описания деталей конкретного CI/CD процесса для отдельного проекта. Для описание этих действий есть Jenkinsfile, который предоставляет гибкость для определения конкретных шагов CI/CD и интеграции с системами контроля версий. Более подробно мы поговорим об этом в следующей главе.Jobs — это раздел конфигурационного файла, который позволяет определить и настроить сборочные задачи с помощью кода. Блок включает в себя:
Разбор примера:
pipeline
: Основной блок, определяющий пайплайн-джобы.agent any
: Определяет, что пайплайн может выполняться на любом доступном агенте Jenkins.stages
: Блок, содержащий этапы пайплайна. Stage — этап.Дополнительные возможности:
Триггеры: Можно добавить триггеры, чтобы джоба запускалась автоматически при определенных условиях, например, по расписанию или при коммите в репозиторий:
triggers {
cron('H 4/* 0 0 1-5')
}
post-conditions
) для выполнения шагов после завершения пайплайна, например, отправка уведомлений или архивирование артефактов.parameters {
string(name: 'BRANCH_NAME', defaultValue: 'main', description: 'Branch to build')
}
Скрипт для развертывания Jenkins в Docker:
#!/bin/bash
# Параметры Jenkins
JENKINS_IMAGE="jenkins/jenkins:lts"
CONTAINER_NAME="jenkins-server"
JENKINS_PORT="8080"
JENKINS_AGENT_PORT="50000"
VOLUME_NAME="jenkins_home"
CONFIG_DIR="$(pwd)/jenkins_configuration"
# Создание тома для хранения данных Jenkins
docker volume create $VOLUME_NAME
# Запуск контейнера Jenkins с JCasC
docker run -d \
--name $CONTAINER_NAME \
-p $JENKINS_PORT:8080 \
-p $JENKINS_AGENT_PORT:50000 \
-v $VOLUME_NAME:/var/jenkins_home \
-v $CONFIG_DIR:/var/jenkins_home/casc_configs \
-e CASC_JENKINS_CONFIG=/var/jenkins_home/casc_configs \
$JENKINS_IMAGE
Пример JCasC конфигурационного файла jenkins.yaml
мы рассматривали выше.
Для настройки CI/CD пайплайна следуйте этим шагам:
После установки перейдите обратно в раздел «Создать Item»
*/main
). Обратите внимание, Jenkinsfile создается без расширения. Если у вас есть подкаталог, в котором находится Jenkinsfile, укажите его в поле «Script Path».Пример Jenkinsfile
pipeline {
agent any
environment {
JENKINS_CONTAINER_NAME = 'new-jenkins-server'
JENKINS_IMAGE = 'jenkins/jenkins:lts'
JENKINS_PORT = '8080'
JENKINS_VOLUME = 'jenkins_home'
}
stages {
stage('Setup Docker') {
steps {
script {
// Установка Docker на сервере, если его нет
sh '''
if ! [ -x "$(command -v docker)" ]; then
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
fi
'''
}
}
}
stage('Pull Jenkins Docker Image') {
steps {
script {
// Скачивание последнего образа Jenkins
sh "docker pull ${JENKINS_IMAGE}"
}
}
}
stage('Cleanup Old Jenkins Container') {
steps {
script {
// Остановка и удаление старого контейнера, если он существует
def existingContainer = sh(script: "docker ps -a -q -f name=${JENKINS_CONTAINER_NAME}", returnStdout: true).trim()
if (existingContainer) {
echo "Stopping and removing existing container ${JENKINS_CONTAINER_NAME}..."
sh "docker stop ${existingContainer} || true"
sh "docker rm -f ${existingContainer} || true"
} else {
echo "No existing container with name ${JENKINS_CONTAINER_NAME} found."
}
}
}
}
stage('Run Jenkins Container') {
steps {
script {
// Запуск Jenkins контейнера с привязкой портов и монтированием volume
sh '''
docker run -d --name ${JENKINS_CONTAINER_NAME} \
-p ${JENKINS_PORT}:8080 \
-p 50000:50000 \
-v ${JENKINS_VOLUME}:/var/jenkins_home \
${JENKINS_IMAGE}
'''
}
}
}
stage('Configure Jenkins (Optional)') {
steps {
script {
// Дополнительная настройка Jenkins через Groovy скрипты или REST API
sh '''
# Пример скрипта для выполнения первичной настройки Jenkins
curl -X POST http://localhost:${JENKINS_PORT}/scriptText --data-urlencode 'script=println("Jenkins is running!")'
'''
}
}
}
}
post {
always {
echo "Jenkins setup and deployment process completed."
}
}
}
Для этого пайплайна использовались следующие файлы:
Dockerfile:
FROM jenkins/jenkins:lts
USER root
RUN apt-get update && apt-get install -y docker.io
docker-compose.yml:
version: '3.7'
services:
jenkins:
build: .
ports:
- "8081:8080"
- "50001:50000"
volumes:
- jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
environment:
- JAVA_OPTS=-Djenkins.install.runSetupWizard=false
networks:
- jenkins-network
volumes:
jenkins_home:
networks:
jenkins-network:
Здесь используются порты 8081 и 50001, чтобы новый развернутый Jenkins мог занять порты 8080 и 50000 соответственно. То есть основной Jenkins, из которого запускается пайплайн, сейчас находится по адресу http://localhost:8081/
. Один из способов проверить, что Jenkins развернулся, это перейти по адресу http://localhost:8080/
, поскольку в пайплайне мы задавали именно его. Так как это новый образ, на главной странице высветится приветственное сообщение с авторизацией:
Выгодные тарифы на облако в Timeweb Cloud
Автоматизация развертывания, обновлений и резервного копирования Jenkins важна для обеспечения надежности и безопасности CI/CD-процессов. Использование современных инструментов дополняет этот процесс множеством полезных функций и ресурсов.
Если вам дальше интересно изучать возможности Jenkins, рекомендуем полезные ресурсы и материалы, которым могут помочь при автоматизации развертывания: