【问题标题】:How do I fail a Jenkins build if a Docker Pipeline Plugin withRun command returns a non-zero exit code?如果 Docker Pipeline Plugin withRun 命令返回非零退出代码,我如何使 Jenkins 构建失败?
【发布时间】:2024-05-02 19:15:04
【问题描述】:

我正在使用Docker Pipeline Plugin 通过 Docker 容器执行我的构建脚本。我注意到,如果在inside() 命令中执行时脚本返回非零退出代码,Jenkins 会将管道执行标记为失败。这个 Jenkinsfile 示例说明了这种情况:

docker.image('alpine').inside() {
  sh 'exit 1'
}

但是,如果我使用 withRun() 命令,类似的 Jenkinsfile 不会 导致构建失败,即使 docker ps -l 命令显示容器以非零状态退出:

node() {
  sh 'touch ./test.sh'
  sh 'echo "exit 1" >> ./test.sh'
  sh 'chmod 755 ./test.sh'

  docker.image('alpine').withRun("-v ${WORKSPACE}:/newDir", '/bin/sh /newDir/test.sh') {container ->
    sh "docker logs ${container.id} -f"
    sh 'docker ps -l'
  }
}

如果容器以非零代码退出,有没有办法让withRun() 构建失败?

【问题讨论】:

    标签: docker jenkins jenkins-plugins jenkins-pipeline


    【解决方案1】:

    一种可能的解决方案:

    docker.withRegistry("https://${REGISTRY}", 'creds-id') {
    
        stage("RUN CONTAINER"){
            Image = docker.image("${IMAGE}-${PROJECT}:${TAG}")
            try {
                c = Image.run("-v /mnt:/mnt")
                sh "docker logs -f ${c.id}"
                def out = sh script: "docker inspect ${c.id} --format='{{.State.ExitCode}}'", returnStdout: true
                sh "exit ${out}"
            } finally {
                c.stop()
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我在withRun() 命令中找不到有关退出代码的更多信息,所以我最终只是从sh 步骤中执行了docker run 命令:

      node() {
        sh 'touch ./test.sh'
        sh 'echo "exit 1" >> ./test.sh'
        sh 'chmod 755 ./test.sh'
        sh "docker run --rm -v ${WORKSPACE}:/newDir alpine /bin/sh /newDir/test.sh"
      }
      

      【讨论】:

      • Hacky解决方案,最好充分利用Image.run()函数
      【解决方案3】:

      运行一个根据docker wait 的输出退出的脚本怎么样?

      sh "exit \$(docker wait ${container.id})"
      

      wait 打印容器的退出代码,如果出错会导致根据sh docs 构建失败:

      通常,以非零状态代码退出的脚本将导致步骤失败并出现异常。

      【讨论】: