首页 文章

使用Jenkins声明性管道为dockerfile代理设置构建args

提问于
浏览
12

我正在使用声明性管道语法在docker容器中执行一些CI工作 .

我注意到Jenkins的Docker插件使用主机中jenkins用户的用户ID和组ID运行一个容器(即如果jenkins用户有用户ID 100和组ID 111,它将运行管道创建一个容器,命令 docker run -u 100:111 ... ) .

我遇到了一些问题,因为容器将与非现有用户一起运行(特别是我遇到了一些没有主目录的用户的问题) . 所以我想创建一个Dockerfile,它将接收用户id和组ID作为构建参数,并在容器内创建一个合适的jenkins用户 . Dockerfile看起来像这样:

FROM ubuntu:trusty
ARG user_id
ARG group_id

# Add jenkins user
RUN groupadd -g ${group_id} jenkins
RUN useradd jenkins -u ${user_id} -g jenkins --shell /bin/bash --create-home
USER jenkins

...

dockerfile代理有一个 additionalBuildArgs 属性,所以我可以读取主机中jenkins用户的用户ID和组ID,并将它们作为构建aguments发送,但我现在遇到的问题似乎是没有办法执行那些在指定代理之前,在声明性管道中执行命令 . 我希望我的Jenkinsfile是这样的:

// THIS WON'T WORK
def user_id = sh(returnStdout: true, script: 'id -u').trim()
def group_id = sh(returnStdout: true, script: 'id -g').trim()

pipeline {
  agent {
    dockerfile {
      additionalBuildArgs "--build-arg user_id=${user_id} --build-arg group_id=${group_id}"
    }
  }
  stages {
    stage('Foo') {
      steps {
        ...
      }
    }
    stage('Bar') {
      steps {
        ...
      }
    }
    stage('Baz') {
      steps {
        ..
      }
    }
    ...
  }
}

我有什么方法可以实现这个目标吗?我也尝试在管道中包装管道指令,但管道需要位于文件的根目录下 .

5 回答

  • 0

    我确认尝试在没有节点的情况下分配user_id和group_id不起作用,正如您所发现的那样,但这对我来说可以分配这些值并稍后访问它们:

    def user_id
    def group_id
    node {
      user_id = sh(returnStdout: true, script: 'id -u').trim()
      group_id = sh(returnStdout: true, script: 'id -g').trim()
    }
    
    pipeline {
      agent { label 'docker' }
      stages {
        stage('commit_stage') {
          steps {
            echo 'user_id'
            echo user_id
            echo 'group_id'
            echo group_id
          }
        }
      }
    }
    

    希望这些也适用于您的 additionalBuildArgs 声明 .

    在评论中,您指出在使用它来配置dockerfile之前,在声明性管道之外找出user_id和group_id的方法最有可能是一个关键缺陷:它发现user_id的slave不一定与之匹配它用来启动基于docker的构建的奴隶 . 我没有任何解决方法,同时保持声明性Jenkinsfile约束 .

    您可以使用全局代理声明来保证所有阶段的一个从属:Jenkins declarative pipeline: What workspace is associated with a stage when the agent is set only for the pipeline?

    但是具有相同标签的多个节点引用不保证相同的工作空间:Jenkins declarative pipeline: What workspace is associated with a stage when the agent is set only for the pipeline?

  • 2

    你也可以像这样添加一个块:

    agent {
        dockerfile {
    
            args '-v /etc/passwd:/etc/passwd -v /etc/group:/etc/group'
        }
    }
    

    这将允许容器具有正确的用户和组ID .

  • 11

    您还可以使用args参数来解决问题 .
    Pipeline Syntax所述:

    docker还可以选择接受一个args参数,该参数可能包含直接传递给docker run invocation的参数 .

    在代理程序部分中使用dockerfile而不是docker时也可以这样做 .

    我遇到了和你一样的问题,以下几行对我来说很好:

    agent { 
                dockerfile { 
                    dir 'Docker/kubernetes-cli' 
                    args '-u 0:0' //Forces Container tu run as User Root                    
                    reuseNode true
                }
            }
    
  • 4

    我相信我们找到了解决这个问题的好方法 .

    我们有一个作为docker实例运行的Jenkins部署,我为/ var / jenkins_home映射了一个卷,并将.ssh文件夹添加到/var/jenkins_home/.ssh

    我们还使用dockerfile agent指令在docker容器内运行所有构建 . 有时我们需要通过git over ssh访问我们的一些私有作曲家库 .

    我们通过安装项目代表(composer)来利用docker图像缓存,这意味着如果我们的deps改变,我们只会重建构建容器 . 这意味着我们需要在docker构建期间注入SSH密钥 .

    See these example files:

    项目/ Jenkinsfile

    def SSH_KEY
    
    node {
      SSH_KEY = sh(returnStdout: true, script: 'cat /var/jenkins_home/.ssh/id_rsa')
    }
    
    pipeline {
      agent {
        dockerfile {
          filename 'Dockerfile'
          additionalBuildArgs '--build-arg SSH_KEY="' + SSH_KEY + '"'
          reuseNode true
        }
      }
      stages {
        stage('Fetch Deps') {
          steps {
            sh 'mv /home/user/app/vendor vendor'
          }
        }
        stage('Run Unit Tests') {
          steps {
            sh './vendor/bin/phpunit'
          }
        }
      }
    }
    

    项目/ Dockerfile

    FROM mycompany/php7.2-common:1.0.2
    
    # Provides the image for building mycompany/project on Jenkins.
    
    WORKDIR /home/user/app
    
    ARG SSH_KEY # should receive a raw SSH private key during build.
    ADD composer.json .
    RUN add-ssh-key "${SSH_KEY}" ~/.ssh/id_rsa && \
        composer install && \
        remove-ssh-keys
    
    # Note: add-ssh-key and remove-ssh-keys are our shell scripts put in
    # the base image to reduce boilerplate for common tasks.
    
  • 3

    如果您拥有Jenkins的管理员权限,则可以添加以下两个脚本批准:

    staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods execute java.lang.String
    staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods getText java.lang.Process
    

    在此URI中: http://${jenkins_host:port}/jenkins/scriptApproval/

    这将允许您以这种方式在master中执行shell命令:

    def user = 'id -u'.execute().text
    node {
       echo "Hello World ${user}"
    }
    

相关问题