Jenkins管道的Docker插件 - UID 1005不存在用户



我正在尝试从Jenkins Pipeline中的Docker容器内部执行SSH命令。我正在使用CloudBees Docker Pipeline插件来旋转容器并执行命令,以及SSH Agent插件来管理我的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

我通过日志梳理,并意识到Docker Pipeline插件会自动告诉容器通过将UID传递给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"
      }
    }
  }
}

@nathan-Thompson提供的解决方案很棒,但是就我而言,即使在主机机器的/etc/passwd中,我也找不到用户!这意味着安装passwd文件没有解决问题。这个问题https://superuser.com/questions/580148/580148/users-not-found-in-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 ********
            """
        }
    }
}

我刚刚找到了我想分享的另一个解决方案。它与现有解决方案区分开来,因为它允许以一个代理而不是每个阶段运行完整的管道。

诀窍是,而不是直接使用图像,而是请参考Dockerfile(可能是构建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)"
    }
  }
}
    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'
                 '''
            }

来自内森·汤普森(Nathan Thompson)提供的解决方案,我将其修改为Jenkins Docker构建容器,该容器在Jenkins Docker-Slave内运行。#docker中的docker

if (validated_parameters.custom_gradle_image){
                docker.image(validated_parameters.custom_gradle_image).inside(" -v /etc/passwd:/etc/passwd -v /var/lib/jenkins/.ssh/:/var/lib/jenkins/.ssh/ "){
                 sshagent(['jenkins-git-io']){
                    sh "${gradleCommand}"
                 }

最新更新