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

aro*_*ero 16 jenkins docker dockerfile

我正在使用声明性管道语法在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

...
Run Code Online (Sandbox Code Playgroud)

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 {
        ..
      }
    }
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

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

bur*_*ttk 13

我确认尝试在没有节点的情况下分配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
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

希望这些也适用于您的additionalBuildArgs陈述.

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

您可以通过使用全局代理声明来保证所有阶段的一个从属:Jenkins声明性管道:当仅为管道设置代理时,哪个工作空间与阶段关联?

但是具有相同标签的多个节点引用不保证相同的工作空间:Jenkins声明性管道:当仅为管道设置代理时,哪个工作空间与阶段关联?


小智 6

您也可以添加如下代码:

agent {
    dockerfile {

        args '-v /etc/passwd:/etc/passwd -v /etc/group:/etc/group'
    }
}
Run Code Online (Sandbox Code Playgroud)

这将使容器具有正确的用户和组ID。


Fab*_*ler 6

您还可以使用 args 参数来解决该问题。
管道语法中所述

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

当在代理部分使用 dockerfile 而不是 docker 时,这也是可能的。

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

       agent { 
            dockerfile { 
                dir 'Docker/kubernetes-cli' 
                args '-u 0:0' //Forces Container tu run as User Root                    
                reuseNode true
            }
        }
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用此解决方案,则该 docker 容器对工作区所做的任何更改也将以“root 用户”身份进行。例如,如果您运行“sh 'touch test-file'”作为管道步骤,您的 Jenkins 工作区将具有 root 拥有的测试文件 - 当 jenkins 稍后尝试清理工作区时,这可能会导致问题。 (3认同)