Jenkins — автоматизация сборки и деплоя

Jenkins — самый известный инструмент непрерывной интеграции (CI): он автоматически собирает проект, прогоняет тесты и разворачивает приложение после каждого изменения кода. В этом уроке ты создашь свои первые сборки, pipelines и настроишь автоматический запуск по коммитам.

Уровень: средний 18 разделов ⏱ 2–3 часа

1. Что такое CI/CD и зачем Jenkins

CI (Continuous Integration) — практика, при которой каждый коммит в общий репозиторий автоматически собирается и проверяется тестами. CD (Continuous Delivery/Deployment) — доведение проверенного кода до продакшена. Руками делать это каждый раз невозможно, поэтому процесс автоматизируют.

Jenkins — сервер автоматизации на Java, который выполняет джобы (jobs): скрипты, привязанные к репозиторию или расписанию. У него тысячи плагинов: интеграции с Git, Docker, JUnit, Slack, SSH и многими другими инструментами.

git push origin main
# -> Jenkins получает уведомление
# -> клонирует код, собирает проект, запускает тесты
# -> публикует отчёт и артефакты
# -> опционально деплоит на сервер
ПрактикаЧто автоматизируетКак часто
CI (интеграция)сборка и тесты после каждого коммитапри каждом изменении
CD (доставка)подготовка релиза, артефакты, репозиториипо готовности
CD (деплой)выкатка кода в продакшенавтоматически или по кнопке
Jenkins часто сравнивают с GitHub Actions и GitLab CI. Разница: Jenkins — самохостируемый и универсальный, а встроенные пайплайны Git-платформ проще для старта.
CI/CD не избавляет от код-ревью. Проверка человеком и автоматические тесты решают разные задачи и дополняют друг друга.

2. Установка Jenkins

Jenkins запускается как Java-приложение. На Ubuntu установка состоит из двух шагов: Java и сам Jenkins из официального репозитория.

sudo apt update
sudo apt install -y openjdk-17-jre

sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc \
  https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key

echo "deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/" | \
  sudo tee /etc/apt/sources.list.d/jenkins.list

sudo apt update
sudo apt install -y jenkins
sudo systemctl enable --now jenkins

Проверь статус и получи первоначальный пароль администратора:

sudo systemctl status jenkins
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Открой http://localhost:8080, введи пароль и следуй мастеру установки плагинов.

После выхода из мастера создай своего пользователя и сразу смени первоначальный пароль — он одинаков у всех установленных инстансов.
По умолчанию Jenkins слушает порт 8080 на всех интерфейсах. Для реального сервера ограничь доступ Nginx reverse proxy (урок Nginx) и брандмауэром, иначе любой сможет открыть страницу администрирования.

3. Первый job

Самый простой вид джобы — Freestyle project: веб-форма, где указываются шаги сборки. Создадим джобу, которая печатает приветствие и показывает переменные окружения.

# New Item -> Freestyle project -> имя hello-job
# Build Steps -> Execute shell:
echo "Hello from Jenkins"
echo "Workspace: $WORKSPACE"
env | sort | head -5

Нажми Build Now и открой номер запуска (например, #1) — там будут лог консоли и статус. Плавающий синий квадрат означает успех, красный — падение сборки.

Тип джобыКогда использовать
Freestyle projectпростые задания, настройка через веб-интерфейс
Pipelineсложные процессы, код в Jenkinsfile (описано далее)
Multibranch Pipelineсборка каждой ветки репозитория автоматически
Folderгруппировка многих джоб проекта
Каждая сборка выполняется в директории $WORKSPACE. После запуска проверь «Workspace» в джобе — там лежит то, что собрал скрипт.
Синий и красный цвета Jenkins унаследовал из истории: синий обозначает успех, жёлтый — нестабильный запуск с упавшими тестами.

4. Pipelines и Jenkinsfile

Pipeline описывает весь процесс сборки кодом — это называется pipeline-as-code. Такой скрипт лежит в репозитории рядом с проектом и версионируется вместе с ним.

Файл Jenkinsfile в корне репозитория:

pipeline {
    agent any

    stages {
        stage('Сборка') {
            steps {
                echo 'Собираем проект...'
                sh 'python -m pip install -r requirements.txt'
            }
        }
        stage('Тесты') {
            steps {
                echo 'Запускаем тесты...'
                sh 'pytest tests/'
            }
        }
        stage('Деплой') {
            steps {
                echo 'Деплоим на staging...'
            }
        }
    }
}

Эта декларативная форма состоит из трёх частей: agent (где выполнять), stages (этапы) и steps (шаги каждого этапа).

БлокНазначение
agent anyиспользовать любой доступный агент
agent { docker {...} }запускать этапы в Docker-контейнере
stageлогически отдельный этап процесса
stepsшаги внутри этапа: sh, echo, git и другие
postдействия после всех этапов (always, success, failure)
В pipeline-скриптах всегда используй sh для shell-команд. Синтаксис Groovy чувствителен к кавычкам: одинарные кавычки не подставляют переменные, а двойные интерполируют ${...}.
Декларативный синтаксис понятнее новичкам и накладывает структуру. Скриптовый (node { ... }) гибче, но сложнее — начинай с декларативного.

5. Триггеры запуска

Сборка может запускаться автоматически: по расписанию, по изменению кода или по вебхуку из Git-платформы. В декларативном pipeline для этого есть блок triggers.

pipeline {
    agent any

    triggers {
        pollSCM('H/5 * * * *')
        cron('H 2 * * *')
    }

    stages {
        stage('Тесты') {
            steps { sh 'pytest tests/' }
        }
    }
}
Поле cronЗначениеСмысл
минутыH/5каждые 5 минут
часыH 2в 2 часа ночи
дни месяца*каждый день
месяц*каждый месяц
день недели1-5будни
Символ H заменяет число хэшем, чтобы не запускать все джобы одновременно. Используй его в полях cron.
Polling репозитория работает только при настройке SCM в джобе. Если подключён вебхук, pollSCM не нужен.

6. Окружение и креденшелы

Пароли, токены и ключи SSH нельзя хранить в конфигурации и в репозитории. Jenkins хранит их в защищённом хранилище Credentials и подставляет в сборку по идентификатору.

Сначала добавь секрет: Dashboard → Manage Jenkins → Credentials → Add, тип Secret text, например идентификатор deploy-token. Использование внутри pipeline:

pipeline {
    agent any
    environment {
        APP_ENV = 'staging'
    }
    stages {
        stage('Публикация') {
            steps {
                withCredentials([string(credentialsId: 'deploy-token',
                                          variable: 'TOKEN')]) {
                    sh 'docker login -u deployer --password-stdin <<< "$TOKEN"'
                }
            }
        }
    }
}
Тип креденшелаЧто хранит
Username with passwordлогин и пароль
Secret textодиночный токен или пароль
Secret fileцелый файл (например, service-account)
SSH Username with private keyключ для подключения по SSH
Встать в withCredentials — обязательное условие. Без него переменная попадёт в общий процесс сборки, а её значение — в лог консоли.
Блок environment задаёт переменные для всего pipeline, а ключевое слово env. даёт доступ к встроенным переменным Jenkins.

7. Интеграция с Git

Jenkins умеет клонировать репозиторий и запускать сборку для определённой ветки. Для этого нужен плагин Git и указание URL репозитория.

pipeline {
    agent any

    triggers { pollSCM('H/5 * * * *') }

    options { skipDefaultCheckout() }

    stages {
        stage('Клонирование') {
            steps {
                git branch: 'main',
                    url: 'https://github.com/yourname/myapp.git',
                    credentialsId: 'github-ssh'
            }
        }
        stage('Тесты') {
            steps { sh 'pytest tests/' }
        }
    }
}

Шаг git скачивает код с ветки main по SSH-креденшелу github-ssh. Если репозиторий публичный, креденшелы не нужны.

ПараметрНазначение
urlадрес репозитория (HTTPS или SSH)
branchветка для сборки
credentialsIdкреденшел с доступом к приватному репозиторию
changelogпоказывать в сборке список коммитов
Для GitHub используй SSH-ключи или fine-grained токены, которые имеют доступ только к нужному репозиторию. Права «на всё» — лишний риск.
Привязка к пулл-реквестам решается плагином GitHub и типом джобы Multibranch Pipeline: он создаёт отдельную сборку на каждую ветку и PR.

8. Отчётность о тестах

Просто запустить тесты мало — нужно собрать результаты и показать их команде. Многие тестовые фреймворки умеют писать отчёты в формате JUnit XML, и Jenkins превращает их в наглядные графики и тренды.

pipeline {
    agent any

    stages {
        stage('Тесты') {
            steps {
                sh 'pytest --junitxml=reports/pytest.xml tests/'
            }
        }
    }

    post {
        always {
            junit 'reports/pytest.xml'
            publishHTML(target: [
                allowMissing: false,
                alwaysLinkToLastBuild: true,
                reportDir: 'htmlcov',
                reportFiles: 'index.html',
                reportName: 'Покрытие кода'
            ])
        }
    }
}

Директива junit разбирает XML-файл, а publishHTML показывает сгенерированный отчёт (например, покрытие pytest-cov) прямо на странице джобы.

ИнструментФайл отчётаЧто видно в Jenkins
pytestreports/pytest.xmlколичество пройденных и упавших тестов
JUnittarget/surefire-reports/*.xmlграфики истории и длительность
pytest-covhtmlcov/index.htmlHTML-отчёт о покрытии
Allureallure-results/красивый веб-отчёт со сценариями
Если тестовый шаг упал, сборка становится красной. Чтобы отчёт успел создаться даже при упавших тестах, собирай его в блоке post { always { ... } }.

9. Артефакты

Артефакты — результаты сборки: собранные бинарники, dist/ и *.whl, Docker-образы. Jenkins умеет сохранять их после каждой сборки и архивировать.

pipeline {
    agent any

    stages {
        stage('Сборка') {
            steps { sh 'python -m build' }
        }
    }

    post {
        success {
            archiveArtifacts artifacts: 'dist/**',
                             fingerprint: true,
                             allowEmptyArchive: false
            stash name: 'release', includes: 'dist/**'
        }
    }
}
ШагНазначениеГде посмотреть
archiveArtifactsдолгое хранение в Jenkinsстраница запуска → Artifacts
stash / unstashпередача между stagesпрямо в pipeline
сторонний репозиторийверсионированные артефактыNexus, Artifactory
Артефакты хранятся в файловой системе Jenkins и могут съесть много места. Задавай диск ретеншн: options { buildDiscarder(logRotator(numToKeepStr: '20')) }.
Для постоянного хранения релизов артефакты лучше выгружать в отдельный репозиторий (Nexus/Artifactory), а в Jenkins оставлять только результаты локальных сборок.

10. Лучшие практики

Чтобы Jenkins не превратился в источник головной боли, придерживайся нескольких правил.

Агент на Docker получает изолированное окружение для каждой сборки:

pipeline {
    agent {
        docker { image 'python:3.12-slim' }
    }

    stages {
        stage('Тесты') {
            steps {
                sh 'pip install -r requirements.txt'
                sh 'pytest tests/'
            }
        }
    }

    options {
        buildDiscarder(logRotator(numToKeepStr: '20'))
        timeout(time: 15, unit: 'MINUTES')
    }
}
КатегорияРекомендация
КодJenkinsfile декларативный и находится в репозитории
Безопасностьсекреты только через Credentials, права по ролям
Окружениеагент в Docker, неизменяемые зависимости
Производительностьтаймауты, limit конкурентости, чистка артефактов
Мониторингуведомления в Slack, статус в коде репозитория
Открытые права на джобы эксплуатируются злоумышленниками: если кто-то может редактировать пайплайн, он получает и доступ к серверу. Настраивай роли через плагин Role-based strategy.

11. Параметризованные сборки

Не каждая сборка одинакова: иногда нужно указать ветку, окружение или версию релиза. Параметры делают джобу интерактивной и позволяют запускать одну и ту же логику с разными значениями.

pipeline {
    agent any

    parameters {
        choice(name: 'ENV', choices: ['staging', 'prod'], description: 'Куда деплоим')
        string(name: 'BRANCH', defaultValue: 'main', description: 'Ветка для сборки')
        booleanParam(name: 'RUN_TESTS', defaultValue: true)
    }

    stages {
        stage('Тесты') {
            when { expression { params.RUN_TESTS } }
            steps { sh 'pytest tests/' }
        }
        stage('Деплой') {
            steps {
                sh "deploy.sh ${params.ENV} ${params.BRANCH}"
            }
        }
    }
}
Сочетайте параметры с when: тесты или тяжёлый деплой запускаются строго по условию.
Параметры, попадающие в shell-команды, экранируйте. Конкатенация без проверки — дыра в безопасности сборки.

12. Мастер и агенты

В большой команде сборки перестают помещаться на одном Jenkins: контроллер (мастер) координирует, а агенты выполняют работу. Каждая сборка направляется на агента по меткам и доступности.

pipeline {
    agent { label 'linux && docker' }

    stages {
        stage('Сборка') {
            steps { sh 'docker build -t app .' }
        }
    }
}
РольЗадача
Контроллервеб-интерфейс, планирование, хранение конфигурации
Агент (node)выполняет stages в своём окружении
Метка (label)группа агентов с общим свойством
Не выполняйте тяжёлые сборки на контроллере: его главная роль — координация, а не вычисления.

13. Shared Libraries: общий код пайплайнов

Когда одинаковые шаги (обёртки docker, уведомления) повторяются в десятках джоб, их выносят в общую библиотеку. Shared Library — репозиторий с кодом на Groovy, подключённый к Jenkins.

// vars/deployApp.groovy (в репозитории библиотеки)
def call(String env) {
    echo "Деплой в ${env}"
}

// Jenkinsfile
library 'devops-lib'

pipeline {
    agent any
    stages {
        stage('Деплой') {
            steps { deployApp('staging') }
        }
    }
}
Начинайте с функций в одном Jenkinsfile и переносите в библиотеку только после третьего повтора одного и того же кода.
Код shared library исполняется с правами джобы: к доступу на запись в неё относитесь как к доступу к самому Jenkins.

14. Безопасность и обслуживание Jenkins

Jenkins — сервер в вашей инфраструктуре, к нему применимы обычные правила: регулярные обновления, ограниченные права, резервные копии и мониторинг диска.

# быстрая проверка диска и перезапуск после обновления
df -h /var/lib/jenkins
sudo systemctl restart jenkins
journalctl -u jenkins -f   # живые логи
ПрактикаКак часто
Обновление Jenkins и плагиновраз в месяц
Бэкап $JENKINS_HOMEежедневно
Проверка свободного местаеженедельно
Аудит прав пользователейперед крупными релизами
Включите защиту от CSRF, почтовые уведомления о сбоях и мониторинг через плагин Prometheus.
Мониторинг и алерты подробнее разбираются в курсах Prometheus и Grafana.

15. Docker-агенты: сборка в контейнерах

Сборки в изолированных контейнерах защищают мастер от «мусора» зависимостей: каждый job стартует с чистого образа, а результат — артефакт, а не замараная машина.

pipeline {
    agent {
        docker { image 'maven:3.9-eclipse-temurin-17' }
    }
    stages {
        stage('Build') { steps { sh 'mvn package' } }
    }
}
Кэшируйте сервер Maven/Gradle в volume: maven-cache:/root/.m2 — это ускоряет первые сборки в 3–5 раз.
Не тяните в образ секреты и не собирайте «каждый раз заново» тяжёлые зависимости. Держите образы и войс в реестре, а не в git.
Docker подробно — курс Docker.

16. Палитры сборок: parallel, matrix и when

Одна пайплайна может собирать проект под разные ОС/версии без дублирования кода — директивы matrix и parallel.

pipeline {
    agent any
    stages {
        stage('Matrix Build') {
            matrix {
                axes {
                    axis { name 'VERSION'; values '8u422', '17', '21' }
                    axis { name 'OS';     values 'linux', 'windows' }
                }
                stages {
                    stage('Test') { steps { ... } }
                }
            }
        }
    }
}
Combination filter исключает «бессмысленные» пары: windows + mac, если в проекте одна ОС.
Слишком «широкие» матрицы перегружают мастера агентов. Начинайте с одной ОС и собирайте остальные по тегу-релизу.

17. Продвинутые техники: Shared pipeline, когда и повтор

Скрапаторы решают три частые задачи: переиспользовать логику, управлять условиями и аккуратно обрабатывать сбои.

// повтор при flaky-тестах
stage('Test') {
    steps {
        retry(2) { sh 'mvn test' }
        timeout(time: 10, unit: 'MINUTES') { sh '...' }
    }
}
post {
    always       { junit 'target/surefire-reports/*.xml' }
    failure      { slackSend color: 'danger', message: "Сборка ${env.JOB_NAME}" }
    success      { archiveArtifacts artifacts: 'target/*.jar' }
}
post-блок — место для уведомлений и сборки артефактов; не пишите их в stages, чтобы не путать условную логику.
retry на тестах прикрывает реальные сбои: фиксируйте, какая именно попытка была успешной, в отчёте.

18. Инструменты аналитики: отчёты, качество, метрики

Jenkins умеет показывать не только «зелёное/красное», но и цифры: покрытие, дефекты, время сборки, уязвимости — через плагины.

ПлагинЧто даёт
JUnit/TestNGтаблица тестов и результаты во времени
Warnings NGпредупреждения компилятора, линтеров
JaCoCoпокрытие кода по репозиторию
OWASP Dependency-Checkуязвимости в зависимостях
pipeline {
    stages {
        stage('Analyze') {
            steps {
                recordCoverage(tools: [[parser: 'JACOCO', pattern: 'target/jacoco.exec']])
            }
        }
    }
}
Введите правило качества: сборка «краснеет», если покрытие упало ниже порога — например, менее 80% ключевых модулей.
Анализ не заменяет код-ревью: покрытие «100% строк» бывает фиктивным. Комбинируйте метрики с практикой ревью.

19. Blue Ocean: визуализация и удобство пайплайнов

Классический интерфейс Jenkins перегружен. Blue Ocean — современный UI для пайплайнов: запуски видны ветками, этапы — карточками, а падения подсвечиваются сразу.

# установить плагин Blue Ocean
# Jenkins → Manage → Plugins → Blue Ocean
2026-09-19 10:00:42 [Pipeline] Start of Pipeline
stage «Build» — green   # шаг выполнен
stage «Test» — red      # fail, открыть фрагмент лога
Настройте для новичков представление «только пайплайны»: этапы понятнее, чем поля фристайл-джобов.
Blue Ocean — удобный слой, но не замена кода: он генерирует тот же Jenkinsfile, который нужно версионировать (раздел 13) и обновлять через ревью.

20. Job DSL: джобы как код

Сотня фристайл-джобов, настроенных руками, не поддерживается. Плагин Job DSL описывает джобы скриптом на Groovy — и генерирует их автоматически при изменении кода.

// jobdsl.groovy
job('build-app') {
  scm { git('https://github.com/org/app.git') }
  steps { shell('npm ci && npm run build') }
  triggers { cron('H/15 * * * *') }
}
// после прогона джоба появляется в Jenkins
Начинайте с Seed: «джоба, которая делает джобы» — весь CI описывается одним репозиторием конфигураций.
Массовая перегенерация перезапишет и джобы с ручными настройками: применяйте обновление аккуратно, а не «всё и сразу».

21. Уведомления о сборках: Telegram, Slack и email

Пайплайны молчат, пока всё зелёное, — но красную сборку команда должна увидеть за минуты. Плагины уведомлений решают это без «лишних совещаний».

КаналПлагинТипичный кейс
Telegramtelegram-notificationsрезультат сборки боту
SlackSlack Notificationканал команды с деталями
EmailMailerполные отчёты
post {
  failure {
    telegramSend(text: "Сборка упала: ${env.BUILD_URL}")
  }
  success {
    slackSend(channel: '#ci', message: 'OK')
  }
}
Шлите в канал только failure и unstable, а успех — сводкой в конце дня: иначе канал превращается в шум.
Токены ботов — секреты: храните их в креденшелах Jenkins (раздел 6), а не в коде пайплайна.

22. Отказоустойчивость: бэкапы и горячий мастер

Jenkins хранит историю сборок, джобы, секреты и плагины в $JENKINS_HOME. Потерять её — потерять всю конфигурацию. Плановый бэкап — правило №1 администрирования.

# бэкап конфигурации
tar czf /backup/jenkins_$(date +%F).tgz \
  /var/lib/jenkins
# восстановление: распаковать и запустить jenkins
Проверяйте восстановление: раз в месяц разворачивайте бэкап в тестовой среде, иначе «страховка» — бумага.
Поверхностный бэкап без проверки restore — это лишь видимость надёжности: реальный тест восстановления важнее наличия файла.

Что дальше

Ты прошёл путь от первого job до полноценного pipeline: триггеры, креденшелы, Git, отчёты и артефакты. Следующие логичные шаги — собрать приложение в Docker внутри пайплайна и выложить на сервер перед Nginx. Если репозиторий на GitHub, сравни подход Jenkins с нативным GitHub Actions, а секреты найди урок HashiCorp Vault.

← Вернуться к курсам