如何在Jenkins的Docker容器中运行多个命令?

我有一个复杂的构build和testing过程,我想在Docker容器中运行。 由于被测软件激活了一些xterm窗口,我使用supervisord在容器内运行X服务器和VNC来启动它们。 然后,一旦容器运行supervisord作为入口点,我可以使用docker exec手动启动构build和testing过程。

我无法确定使用Jenkins和Docker Pipeline插件执行此操作的方法。 目前版本的插件似乎有一些限制,我不能充分解决。 这是基本的想法:

 node { stage('Fetch installer') { // SCM commands go here } def image = docker.image('metatest') image.inside() { stage('Run installer') { sh "./installer.sh" } stage('Run tests') { sh "/opt/custom/run_tests.sh" } } } 

然而,这种方法被破坏了,因为image.inside()方法覆盖了默认用户(它设置为Jenkins的用户ID)和入口点。 我需要能够使用默认的root用户启动Docker容器,因为X服务器进程必须是root用户。 但是,我需要在容器中运行安装和testing,作为Jenkins非root用户,以便Jenkins可以pipe理输出材料。

对于logging, image.inside()在启动Docker容器时设置了许多非常有用的参数:

 docker run -t -d -u 113:123 \ -w "/var/lib/jenkins/workspace/TestProj" \ -v "/var/lib/jenkins/workspace/TestProj:/var/lib/jenkins/workspace/TestProj:rw" \ -v "/var/lib/jenkins/workspace/TestProj@tmp:/var/lib/jenkins/workspace/TestProj@tmp:rw" \ -e ******** -e ******** -e ******** -e ******** -e ******** \ -e ******** -e ******** -e ******** -e ******** -e ******** \ -e ******** -e ******** -e ******** -e ******** -e ******** \ -e ******** -e ******** -e ******** \ --entrypoint cat \ metatest 

Jenkins uid:gid pair的设置,工作目录,主机共享的卷以及Jenkins环境variables(在这里被屏蔽)都是非常有用的,并且在Jenkins中手动重现是非常烦人的。 在这种情况下,ENTRYPOINT覆盖不是有用的。

不幸的是,Docker Pipeline命令image.inside()实现不允许我将容器的设置与正在创build的正在运行的容器中的阶段的执行分开。 还有一些其他的命令用于这个过程的一部分,但是它们似乎缺less了实际的执行步骤,而且它们不包括很多有用的参数设置。

换句话说,我想要做这样的事情:

 node { stage('Fetch installer') { // SCM commands go here } def image = docker.image('metatest') def container = image.run('-u 0:0') container.inside() { stage('Run installer') { sh "./installer.sh" } stage('Run tests') { sh "/opt/custom/run_tests.sh" } } stage('Check output') { // run a script on the Jenkins host } container.inside() { stage('Final script step') { sh "./another_script.py" } } container.stop() container.remove() } 

主要区别是:

  1. image.run()为Jenkins设置了相同的uid:gid对,然后再加上所有的工作空间,体积和环境variables,但不是ENTRYPOINT覆盖。
  2. container.inside()存在并允许我执行正在运行的容器内的执行步骤。
  3. container.inside()设置与第1步相同的参数。
  4. container.stop()只停止容器,而remove()实际上删除它。 不需要将它们组合起来。

使用这种方法,我可以在容器中执行单独的命令,然后在Jenkins中运行一些额外的命令,返回容器,停止并重新启动容器,在移除容器之前保存容器的图像等等。所有这些都是更多的目前的插件很难。

我已经向Jenkins发出了一个请求来添加这个分离 ,但是我需要一个没有这个方法的方法。 有任何想法吗?