【问题标题】:Jenkins docker container always adds cat commandJenkins docker 容器总是添加 cat 命令
【发布时间】:2019-08-17 13:53:30
【问题描述】:

我正在创建 Jenkins 管道以在 Docker 容器上运行 terraform。

这是我的管道脚本。

pipeline {
    agent {
        docker {
            image 'hashicorp/terraform:full'
            args '--entrypoint=/bin/bash'
        }
    }
    stages {
        stage('execute') { 
            steps {
                sh 'terraform --version' 
            }
        }
    }
}

在 Jenkins 上运行此管道时,出现以下错误。

$ docker run -t -d -u 995:993 --entrypoint=/bin/bash -w /var/lib/jenkins/workspace/terraform -v /var/lib/jenkins/workspace/terraform:/var/lib/jenkins/workspace/terraform:rw,z -v /var/lib/jenkins/workspace/terraform@tmp:/var/lib/jenkins/workspace/terraform@tmp:rw,z -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** -e ******** hashicorp/terraform:full cat

$ docker top a0b801d657d0fffdfa95c387564128b130ab1d28569ad59bd0151c8b7faf6ffd -eo pid,comm

java.io.IOException: Failed to run top 'a0b801d657d0fffdfa95c387564128b130ab1d28569ad59bd0151c8b7faf6ffd'. Error: Error response from daemon: Container a0b801d657d0fffdfa95c387564128b130ab1d28569ad59bd0151c8b7faf6ffd is not running

这似乎是 Jenkins 添加了一个 cat 命令来运行镜像 hashcorp/terraform:full。

请注意,我已经使用 --entrypoint=/bin/bash 覆盖了 /bin/bash 的入口点,因为 hashicorp/terraform:full em> 已经定义了一个入口点。

【问题讨论】:

  • 您的问题是关于为什么将cat 命令添加到run,还是为什么您会收到错误以及如何修复它?这两个问题无关。
  • cat 是一种让容器的主进程无限期打开直到作业结束的技巧。它替换了容器的CMD。容器开始分离,然后另一个进程附加到它,以便控制台命令可以运行。就个人而言,我不喜欢这种方法。
  • 这是超级蹩脚,因为容器并不总是开箱即用,如果你在入口点和命令之间设置了一个链式系统,它就不能按设计工作。这是詹金斯的一个黑客,所以我同意这个评论者fix should be in the Jenkinsfile。事实上,您的entrypoint 可能会毫无意义地运行,它会破坏paradigm of entrypoint-cmd 关系。
  • 因为原生cmd 不运行并且entrypoint 可能会变得无用,所以您必须发出sh 命令将它们镜像到Jenkins 管道中。

标签: docker jenkins jenkins-pipeline terraform


【解决方案1】:

我必须将 ENTRYPOINT 更改为空,以禁用 terraform 容器定义中的入口点定义。而且我认为light 图像足以执行 terraform。

我得到了它使用以下脚本:

pipeline {
  agent {
    docker {
        image 'hashicorp/terraform:light'
        args '--entrypoint='
    }
  }
  stages {
    stage('execute') { 
        steps {
            sh 'terraform --version' 
        }
    }
  }
}

【讨论】:

  • 非常适合那些无法升级插件的人。谢谢。
【解决方案2】:

这似乎是 jenkins 中 docker-workflow-plugin 的默认行为。 [已修复 JENKINS-41316] 将“内部”切换回 CMD,检测入口点是否设计不当 #116 https://github.com/jenkinsci/docker-workflow-plugin/pull/116

我们运行图像指定的任何进程(甚至 sh -c) 他们的目的是 That will break in most images, since for this purpose we need to start a container, pause it while we exec some stuff, and then stop it, without having to guess what its “main command” might run and when it might exit on its own. That is why we cat (I also have considered sleep infinity or some POSIX-compliant variant).

https://issues.jenkins-ci.org/browse/JENKINS-39748

代码在这里:https://github.com/jenkinsci/docker-workflow-plugin/blob/50ad50bad2ee14eb73d1ae3ef1058b8ad76c9e5d/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java#L184

他们希望容器 /* 预计会挂起直到被杀死 */。


原答案:

你会尝试在没有 -d 选项的情况下运行(这意味着在后台运行)

docker run -it --entrypoint=/bin/bash hashicorp/terraform:full

然后你可以进入容器运行你想要的任何东西。

以nginx为例:

docker run -it --entrypoint=/bin/bash nginx
root@e4dc1d08de1d:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@e4dc1d08de1d:/# cat /var/log/
apt/      btmp      dpkg.log  faillog   lastlog   nginx/    wtmp
root@e4dc1d08de1d:/# cat /var/log/faillog
root@e4dc1d08de1d:/#

【讨论】:

  • docker run 命令是 Jenkins 服务器根据流水线配置生成的,不可直接编辑。
【解决方案3】:

在我的情况下,entrypoint 给我带来了一些麻烦,所以我需要通过将空的 entrypoint 参数传递给 inside 方法来覆盖它,如下所示:

pipeline {
    agent { 
        label 'some_label'
    }
    stages {
        stage('execute') { 
            steps {
                script {
                    img = docker.build("docker_image_name:docker_image_tag")
                    
                    img.inside('--entrypoint= -e NODE_ENV=test') {
                        sh 'npm install --dev'
                        sh 'npm run test'
                    }                   
                }
            }
        }
    }
}

此示例类似于@S.Spieker 注释,但语法不同。

备注:像npm test这样的npm命令在node js项目之间可能会有所不同,所以你需要从开发者那里获取相关命令。

如果此示例仍然不适合您,那么您可能需要更改您的 docker 映像 entrypoint,如下所示:https://github.com/SonarSource/sonar-scanner-cli-docker/pull/31/files

您可以在此处了解有关 docker-flow 插件的更多信息:https://docs.cloudbees.com/docs/admin-resources/latest/plugins/docker-workflow

更多示例:Jenkins: How to use JUnit plugin when Maven builds occur within Docker container

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多