【问题标题】:Docker Plugin for Jenkins Pipeline - No user exists for uid 1005用于 Jenkins 管道的 Docker 插件 - 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

【问题讨论】:

    标签: jenkins docker ssh jenkins-plugins


    【解决方案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。
        猜你喜欢
        • 2019-06-16
        • 1970-01-01
        • 2017-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-16
        • 1970-01-01
        相关资源
        最近更新 更多