用于 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 管道中失败

jenkins 管道脚本中 docker 容器的 if else 条件

text Jenkins管道支持k8 / docker