Jenkins Pipeline的Docker插件 - uid 1005没有用户

Nat*_*son 10 ssh jenkins jenkins-plugins docker

我正在尝试从Jenkins管道中的Docker容器内执行SSH命令.我正在使用CloudBees Docker Pipeline插件来启动容器并执行命令,使用SSH代理插件来管理我的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"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当SSH命令运行时,我收到此错误:

+ ssh -vvv -o StrictHostKeyChecking=no ubuntu@example.org uname -a
No user exists for uid 1005
Run Code Online (Sandbox Code Playgroud)

Nat*_*son 18

我梳理了日志并意识到Docker Pipeline插件通过传递UID作为命令行参数,自动告诉容器使用登录主机的同一用户运行:

$ docker run -t -d -u 1005:1005 [...]
Run Code Online (Sandbox Code Playgroud)

我决定通过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"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 你是我的英雄。最后我可以从管道中进行 git 推送。多谢。在相关的詹金斯错误中评论您的解决方案可能是个好主意。 (3认同)

Flo*_*ann 8

我刚刚找到了这个问题的另一个解决方案,我想分享一下。它与现有解决方案的不同之处在于,它允许在一个代理中运行完整的管道,而不是每个阶段。

诀窍是,不要直接使用图像,而是引用 Dockerfile(可能是构建FROM原始文件),然后添加用户:

# Dockerfile
FROM node

ARG jenkinsUserId=
RUN if ! id $jenkinsUserId; then \
    usermod -u ${jenkinsUserId} jenkins; \
    groupmod -g ${nodeId} jenkins; \
  fi
Run Code Online (Sandbox Code Playgroud)
// Jenkinsfile
pipeline {
  agent {
    dockerfile {
      additionalBuildArgs "--build-arg jenkinsUserId=\$(id -u jenkins)"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


hpa*_*nia 5

@nathan-thompson 提供的解决方案很棒,但就我而言,即使在/etc/passwd主机中我也找不到用户!这意味着挂载passwd文件没有解决问题。这个问题https://superuser.com/questions/580148/users-not-found-in-etc-passwd建议一些用户使用 LDAP 等身份提供者登录主机。

解决方案是找到一种方法将正确的行添加到passwd容器上的文件中。调用getent passwd $USER主机将为passwd运行容器的 Jenkins 用户提供线路。

我添加了一个在节点(而不是 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 ********
            """
        }
    }
}
Run Code Online (Sandbox Code Playgroud)