Проблема декларативного конвейера Jenkins при запуске docker -in- docker - PullRequest
1 голос
/ 03 августа 2020

Я только что столкнулся с проблемой при запуске декларативного конвейера Jenkins на сервере Jenkins, который сам работает внутри Docker, имея доступ к docker.sock с хоста.

Структура конвейера такова. довольно просто:

pipeline {
    agent {
        docker { image 'gradle:jdk11' }
    }
    stages {
        stage('Checkout') {
            steps {
                // ...
            }
        }
        stage('Assemble public API documentation') {
            environment {
                // ...
            }
            steps {
                // ...
            }
        }
        stage('Generate documentation') {
            steps {
                // ...
            }
        }
        stage('Upload documentation to Firebase') {
            agent {
                docker {
                    image 'node:12'
                    reuseNode false
                }
            }
            steps {
                // ...
            }
        }
    }
}

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

[Pipeline] stage
[Pipeline] { (Upload documentation to Firebase)
[Pipeline] getContext
[Pipeline] isUnix
[Pipeline] sh
+ docker inspect -f . node:12
/var/jenkins_home/workspace/publish_public_api_doc@tmp/durable-bc4d65d1/script.sh: 1: /var/jenkins_home/workspace/publish_public_api_doc@tmp/durable-bc4d65d1/script.sh: docker: not found
[Pipeline] isUnix
[Pipeline] sh
+ docker pull node:12
/var/jenkins_home/workspace/publish_public_api_doc@tmp/durable-297d223a/script.sh: 1: /var/jenkins_home/workspace/publish_public_api_doc@tmp/durable-297d223a/script.sh: docker: not found
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
$ docker stop --time=1 367647f97c9eed52bf85c13c2bc2203bb7194adac803d37cab0e0d0435325efa
$ docker rm -f 367647f97c9eed52bf85c13c2bc2203bb7194adac803d37cab0e0d0435325efa
[Pipeline] // withDockerContainer
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 127
Finished: FAILURE

Я не совсем понимаю, что здесь происходит. Чтобы отладить это, я вошел в систему на этой машине и выполнил команду docker с хоста, а также из запущенного контейнера Jenkins, и он заработал. Это настроено так, что клиент Docker установлен в образе, то есть сам двоичный файл не используется совместно с контейнером. Поскольку команда docker «не найдена», единственное объяснение, которое у меня есть, это то, что команда docker для запуска агента для заключительного этапа не выполняется в Jenkins «верхнего уровня». контейнер, но в JDK, в котором нет исполняемого файла docker. Однако это могло бы показаться неожиданным, если бы не ошибкой. Я был бы благодарен, если бы кто-нибудь пролил свет на это.

1 Ответ

1 голос
/ 02 сентября 2020

Агенты / узлы конвейера Jenkins В вашем конвейере указан агент для работы на самом верхнем уровне. Конвейер будет выполнять все команды на этом агенте (или в контейнере docker в вашем сценарии), пока не будет указан другой агент. Когда указан новый агент, агент верхнего уровня будет подключаться к нему через некоторый протокол, и новый агент выполнит все этапы / шаги конвейера, которые находятся в пределах этой области действия агентов. После выхода за пределы области действия соединение с новым агентом будет закрыто, и агент верхнего уровня снова выполнит все команды.

Что вызывает ошибку? Четвертый этап пытается изменить контекст выполнения на нового агента. Текущий агент, контейнер gradle:jdk11, выполнит шаги для подключения к этому новому агенту. Поскольку новый агент является контейнером docker, контейнер gradle:jdk11 попытается использовать саму команду docker, чтобы развернуть новый контейнер. Как вы и подозревали, в этом контейнере нет docker двоичного файла / службы.

Почему такое ожидаемое поведение? Предположим, что агент верхнего уровня - это другая физическая машина, подключенная через tcp или s sh, а не через контейнер docker. На этой машине должны быть установлены все инструменты для компиляции, создания документов, запуска модульных тестов и т. Д. c. Например, он не будет использовать двоичный файл doxygen, установленный на мастере Jenkins, поскольку он должен сам предоставлять это (выдает ошибки, если doxygen не существует в $PATH). Точно так же этой машине потребуется программа установки docker, чтобы раскрутить контейнер на четвертом этапе.

Как мне заставить работать конвейер?

  • Вы можете создать свой собственный образ docker, наследующий от gradle:jdk11, и совместно использовать docker хост-систем. Это позволит вашему пользовательскому изображению раскрутить изображение docker, необходимое на четвертом этапе. Вы могли бы использовать agent { docker { image 'my-custom-img' } } в глобальной области.

  • В качестве альтернативы вы можете использовать главный агент (или другие физические машины) в глобальной области, и каждый этап запускает свой собственный контейнер. На каждом этапе будет чистая рабочая среда, поэтому вам нужно будет использовать stash / unstash или смонтированный том для совместного использования src / docs между этапами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...