Gymterview
middle

Как Jenkins взаимодействует с Docker?

Интеграция Jenkins с Docker — это использование Docker-контейнеров в качестве изолированных сред для выполнения сборок, тестирования и упаковки приложений в рамках CI/CD пайплайна.

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

1. Docker как агент сборки

Каждая сборка выполняется в чистом контейнере — изоляция, воспроизводимость, отсутствие конфликтов между проектами:

Пример
pipeline {
    agent {
        docker {
            image 'maven:3.9-eclipse-temurin-17'
            args '-v $HOME/.m2:/root/.m2 --network=host'
        }
    }
    stages {
        stage('Build') {
            steps { sh 'mvn clean package' }
        }
    }
}

Ключевой приём — монтирование кэша Maven (-v $HOME/.m2:/root/.m2), чтобы зависимости не скачивались заново при каждой сборке.

2. Разные Docker-образы для разных стадий

Каждая стадия пайплайна может использовать свой образ с нужным набором инструментов:

Пример: разные образы для сборки, тестов и публикации Docker-образа
pipeline {
    agent none
    stages {
        stage('Build') {
            agent { docker { image 'maven:3.9-eclipse-temurin-17' } }
            steps { sh 'mvn clean package -DskipTests' }
        }
        stage('Test') {
            agent { docker { image 'maven:3.9-eclipse-temurin-17' } }
            steps { sh 'mvn test' }
        }
        stage('Build Docker Image') {
            agent { label 'docker' }
            steps {
                script {
                    def app = docker.build("company/my-app:${env.BUILD_NUMBER}")
                    docker.withRegistry('https://nexus.company.com:8083', 'nexus-credentials') {
                        app.push()
                        app.push('latest')
                    }
                }
            }
        }
    }
}

3. Docker Compose для интеграционных тестов

Когда интеграционные тесты требуют внешних зависимостей (база данных, брокер сообщений, кэш), Docker Compose позволяет поднять всё окружение прямо на агенте:

Пример
stage('Integration Tests') {
    steps {
        sh 'docker-compose -f docker-compose.test.yml up -d'
        sh 'mvn verify -Pintegration-tests'
    }
    post {
        always {
            sh 'docker-compose -f docker-compose.test.yml down -v'
        }
    }
}

Блок post { always { ... } } гарантирует остановку контейнеров даже при падении тестов.

4. Dockerfile как агент

Если ни один публичный образ не подходит, можно указать Dockerfile из репозитория проекта — Jenkins соберёт из него образ и запустит сборку внутри:

Пример
agent {
    dockerfile {
        filename 'Dockerfile.build'
        dir 'ci'
        additionalBuildArgs '--build-arg MAVEN_VERSION=3.9'
    }
}

Сравнение подходов к использованию Docker в Jenkins

Подход Когда использовать Преимущество
docker { image '...' } Стандартные инструменты (Maven, Gradle, Node) Простота, готовые образы
dockerfile { ... } Нужен специфичный набор инструментов Полный контроль над окружением
Docker Compose Интеграционные тесты с зависимостями Полное окружение для тестов
docker.build() + docker.push() Упаковка приложения в Docker-образ Публикация образа в registry

Вывод

Docker в Jenkins решает проблему «на моей машине работает» и обеспечивает полную воспроизводимость сборок. Эфемерные контейнеры-агенты — это стандарт в современных CI/CD пайплайнах.

На собеседовании: могут спросить, зачем монтировать .m2 при использовании Docker-агента. Ответ: чтобы Maven не скачивал все зависимости при каждой сборке — кэш зависимостей сохраняется между запусками контейнера на хосте.