用于 Jenkins 管道的 Docker 插件 - uid 1005 不存在用户
Posted
技术标签:
【中文标题】用于 Jenkins 管道的 Docker 插件 - uid 1005 不存在用户【英文标题】:Docker Plugin for Jenkins Pipeline - No user exists for uid 1005 【发布时间】:2017-07-13 06:27:00 【问题描述】:我正在尝试从 Jenkins 管道中的 Docker 容器内部执行 SSH 命令。我使用CloudBees Docker Pipeline Plugin 启动容器并执行命令,使用SSH Agent Plugin 管理我的SSH 密钥。这是我的 Jenkinsfile 的基本版本:
node
step([$class: 'WsCleanup'])
docker.image('node').inside
stage('SSH')
sshagent (credentials: [ 'MY_KEY_UUID' ])
sh "ssh -vvv -o StrictHostKeyChecking=no ubuntu@example.org uname -a"
当 SSH 命令运行时,我得到这个错误:
+ ssh -vvv -o StrictHostKeyChecking=no ubuntu@example.org uname -a
No user exists for uid 1005
【问题讨论】:
【参考方案1】:我梳理了日志,发现 Docker Pipeline 插件通过将 UID 作为命令行参数传递,自动告诉容器使用登录主机的同一用户运行:
$ docker run -t -d -u 1005:1005 [...]
我决定通过在每个环境中运行 cat /etc/passwd
来检查主机和容器中存在哪些用户。果然,每个人的用户列表都不一样。 1005 是主机上的 jenkins 用户,但容器中不存在该 UID。为了解决这个问题,我在启动时将 /etc/passwd
从主机安装到容器:
node
step([$class: 'WsCleanup'])
docker.image('node').inside('-v /etc/passwd:/etc/passwd')
stage('SSH')
sshagent (credentials: [ 'MY_KEY_UUID' ])
sh "ssh -vvv -o StrictHostKeyChecking=no ubuntu@example.org uname -a"
【讨论】:
你是我的英雄。最后,我可以从管道进行 git push 。非常感谢。在相关的詹金斯错误中评论您的解决方案可能是一个好主意。 也许吧,但我想替换容器中的密码文件可能会导致一些真正的权限或所有权问题。我不反对解决方案,只是保持沉默。 如果您需要将主机的/etc/passwd
挂载到 Docker 容器中,我还建议您将 /etc/passwd
挂载为 ro
(只读)。
我想将一个或多或少敏感的主机文件(如/etc/passwd
)暴露给容器是一种不好的做法。我想将args '-u user:user'
设置为该图像中存在的user
是更好的选择。即使是root
。【参考方案2】:
@nathan-thompson 提供的解决方案很棒,但在我的情况下,即使在主机的/etc/passwd
中我也找不到用户!这意味着挂载passwd
文件并没有解决问题。这个问题https://superuser.com/questions/580148/users-not-found-in-etc-passwd 建议一些用户使用 LDAP 等身份提供者登录主机。
解决方案是找到一种方法将正确的行添加到容器上的 passwd
文件中。在主机上调用 getent passwd $USER
将为运行容器的 Jenkins 用户提供 passwd
行。
我添加了一个在节点(而不是 docker 代理)上运行的步骤来获取该行并将其保存在一个文件中。然后在下一步中,我将生成的passwd
安装到容器中:
stages
stage('Create passwd')
steps
sh """echo \$(getent passwd \$USER) > /tmp/tmp_passwd
"""
stage('Test')
agent
docker
image '*******'
args '***** -v /tmp/tmp_passwd:/etc/passwd'
reuseNode true
registryUrl '*****'
registryCredentialsId '*****'
steps
sh """ssh -i ********
"""
【讨论】:
【参考方案3】:我刚刚找到了这个问题的另一个解决方案,我想分享一下。它与现有解决方案的不同之处在于它允许在一个代理中运行完整的管道,而不是每个阶段。
诀窍是,而不是直接使用图像,而是引用 Dockerfile(可能是 build FROM
原始文件),然后添加用户:
# Dockerfile
FROM node
ARG jenkinsUserId=
RUN if ! id $jenkinsUserId; then \
usermod -u $jenkinsUserId jenkins; \
groupmod -g $nodeId jenkins; \
fi
// Jenkinsfile
pipeline
agent
dockerfile
additionalBuildArgs "--build-arg jenkinsUserId=\$(id -u jenkins)"
【讨论】:
【参考方案4】: agent
docker
image 'node:14.10.1-buster-slim'
args '-u root:root'
environment
SSH_deploy = credentials('e99988ea-6bdc-45fc-b9e1-536b875bcac7')
stage('build')
steps
sh '''#!/bin/bash
eval $(ssh-agent -s)
cat $SSH_deploy | tr -d '\r' | ssh-add -
touch .env
echo 'REACT_APP_BASE_API = "//172.22.132.115:8080"' >> .env
echo 'REACT_APP_ADMIN_PANEL_URL = "//172.22.132.115"' >> .env
yarn install
CI=false npm run build
ssh -t -o StrictHostKeyChecking=no root@172.22.132.115 'rm -rf /usr/local/src/build'
scp -r -o StrictHostKeyChecking=no build root@172.22.132.115:/usr/local/src/
ssh -t -o StrictHostKeyChecking=no root@172.22.132.115 'systemctl restart nginx'
'''
【讨论】:
遗憾的是这个解决方案没有进一步的解释。重要的部分是args '-u root:root'
,因为它覆盖了 jenkins 默认设置为 jenkins uid。以上是关于用于 Jenkins 管道的 Docker 插件 - uid 1005 不存在用户的主要内容,如果未能解决你的问题,请参考以下文章
从 kubernetes 插件 / jenkins 中的 gcr 拉取 docker 图像的问题
Jenkins在Docker上。 — Hello World示例构建失败
来自 AWS ECR 的 Jenkins 管道 Docker 代理
npm install 在 docker 的 jenkins 管道中失败