gpt4 book ai didi

docker - 运行 docker-in-docker 时 Jenkins 声明性管道问题

转载 作者:行者123 更新时间:2023-12-02 19:16:35 26 4
gpt4 key购买 nike

我刚刚在 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 容器中执行,而是在没有 docker 的 JDK 容器中执行。里面可执行。
然而,这似乎是出乎意料的,如果不是一个错误的话。
如果有人对此有所了解,我将不胜感激。

最佳答案

Jenkins 管道代理/节点
您的管道已指定要在最顶层运行的代理。管道将在该代理上(或在您的场景中的 docker 容器内)执行所有命令,直到指定另一个代理。指定新代理时,顶级代理将通过某种协议(protocol)连接到它,新代理将执行此代理范围内的所有管道阶段/步骤。一旦超出范围,与新代理的连接将关闭,顶级代理将再次执行所有命令。
是什么导致了错误?
第四阶段尝试将执行上下文更改为新代理。当前代理,gradle:jdk11容器,将执行连接到这个新代理的步骤。由于新代理是一个 docker 容器,gradle:jdk11容器将尝试使用 docker 命令本身来启动新容器。
正如您所怀疑的,此容器中没有 docker 二进制/服务。
为什么这是预期的行为?
假设顶层代理是通过 tcp 或 ssh 连接的不同物理机,而不是 docker 容器。这台机器需要安装所有用于编译、生成文档、运行单元测试等的工具。它不会使用安装在 Jenkins 主机上的 doxygen 二进制文件,因为它应该自己提供(如果 $PATH 中不存在 doxygen,则会抛出错误)。同样,这台机器需要 docker 安装程序在第四阶段启动容器。
我怎样才能让我的管道正常工作?

  • 您可以创建自己的自定义 docker 镜像,继承自 gradle:jdk11。并共享主机系统的 docker。这将允许您的自定义图像启动第四阶段所需的 docker 图像。您将使用 agent { docker { image 'my-custom-img' } }在全局范围内。
  • 或者,您可以在全局范围内使用主代理(或其他物理机器),并让每个阶段启动自己的容器。每个阶段都有一个干净的工作环境,所以你需要使用stash/unstash或安装的卷以在阶段之间共享 src/docs。
  • 关于docker - 运行 docker-in-docker 时 Jenkins 声明性管道问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63230695/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com