docker - 从单个 Jenkinsfile 运行多个 Docker 容器

标签 docker jenkins groovy jenkins-pipeline

所以我花了一整天的时间试图弄清楚如何用多个 Docker 镜像配置一个简单的 Jenkins 流水线,但我一点也不高兴。

我需要在几个不同的 docker 容器上执行几个阶段(准备、构建、测试、文档)(目前我只选择了三个标准 Python 容器)。如果它们可以并行运行就好了,但我只找到了这个解决方案,它将所有阶段合并为一个(从而在 Blue Ocean UI 中创建了一个信息量不大的概述):Jenkins Pipeline Across Multiple Docker Images

所以我最终得到了下面的配置,这很丑陋(到处都是代码重复),但或多或​​少地在经典 UI 中创建了一个漂亮的概述:

Classic UI stages

Blue Ocean 用户界面中信息量不大的概述

Blue Ocean stages overview

以及来自 junit 的可接受的测试概述,它结合了每个阶段的所有测试,但如果任何测试失败,则会显示相应的“版本”:

junit

然而,最烦人的是,你看不到哪一步失败了。如果 Python 2.7 失败,其他所有内容也会被标记为失败,您甚至看不到哪个阶段失败了。

我尝试了很多不同的方法,我想知道应该如何做到这一点。这对 Jenkins 来说应该是一件很常见的事情,所以我想我在这个(对我来说绝对是新的)管道/节点/标签/阶段/步骤/声明/脚本/groovy/blueocean 东西中有一些普遍的误解......

应该可以为每个 docker 容器定义一些(可能是可定制的阶段/步骤)列表,并并行运行它们并让它在 Blue Ocean 和经典 UI 中很好地显示,不是吗?

node {
    stage("Python 2.7.14") {
        checkout scm
        docker.image('python:2.7.14').inside {  // just a dummy for now
            stage("Prepare") { sh 'python --version' }
            stage("Build") { sh 'ls -al' }
        }
    }
    stage("Python 3.5.4") {
        checkout scm
        docker.image('python:3.5.4').inside {
            stage("Prepare") { sh 'python -m venv venv' }
            stage("Build") {
                sh """
                    . venv/bin/activate
                    make install-dev
                """
            }
            stage('Test') {
                sh """
                    . venv/bin/activate
                    make test
                """
            }
            stage('Docs') {
                sh """
                    . venv/bin/activate
                    make doc-dependencies
                    cd docs
                    make html
                """
            }
        }
    }
    stage("Python 3.6.4") {
        checkout scm
        docker.image('python:3.5.4').inside {
            stage("Prepare") { sh 'python -m venv venv' }
            stage("Build") {
                sh """
                    . venv/bin/activate
                    make install-dev
                """
            }
            stage('Test') {
                sh """
                    . venv/bin/activate
                    make test
                """
            }
            stage('Docs') {
                sh """
                    . venv/bin/activate
                    make doc-dependencies
                    cd docs
                    make html
                """
            }
        }
    }
}

更新:这是当步骤失败时 Blue Ocean UI 中的样子,在这种情况下,Python 3.5.4 和 3.6.4 中的“测试”都失败了,但看起来一切都失败了。
Test step failed

此外,Python 2.7.14 和 3.5.4 阶段已折叠,无法单独查看。如果我点击其中一个,所有步骤都显示为绿色,尽管在这种情况下 . venv/bin/activate make test失败的:

Failed test step is shown in green

最佳答案

所以这就是我的结局。肯定有更好的解决方案,但我必须继续前进。我希望及时收集一些(更好的)答案,我不会将其标记为“解决方案”;)

首先,感谢 Stephen Kings 的幻灯片(标题说“声明性”,但有一些关于脚本化流水线的很好的例子):(Declarative) Jenkins Pipelines

这是我的 gist on GitHub使用以下代码段:

def docker_images = ["python:2.7.14", "python:3.5.4", "python:3.6.2"]

def get_stages(docker_image) {
    stages = {
        docker.image(docker_image).inside {
            stage("${docker_image}") {
                echo 'Running in ${docker_image}'
            }
            stage("Stage A") {
                switch (docker_image) {
                    case "python:2.7.14":
                        sh 'exit 123'  // for python 2.7.14 we force an error for fun
                        break
                    default:
                        sh 'sleep 10'  // for any other docker image, we sleep 10s
                }
                sh 'echo this is stage A'  // this is executed for all
            }
            stage("Stage B") {
                sh 'sleep 5'
                sh 'echo this is stage B'
            }
            stage("Stage C") {
                sh 'sleep 8'
                sh 'echo this is stage C'
            }

        }
    }
    return stages
}

node('master') {
    def stages = [:]

    for (int i = 0; i < docker_images.size(); i++) {
        def docker_image = docker_images[i]
        stages[docker_image] = get_stages(docker_image)
    }

    parallel stages
}

我试图使它易于使用:
  • 您将 Docker 镜像添加到顶部的列表中,然后定义 stagesget_stages()功能
  • 添加常用阶段和步骤
  • 如果任何 Docker 镜像需要特殊处理(例如我的示例中的 python:2.7.14),您可以使用一个简单的 switch .这也可以通过特殊情况的双映射('images'->'stage'='steps')和默认值的后备双映射来实现,但我将把它留给读者作为练习。 (老实说,我想不出正确的、支持的 Groovy-lang 语法)

  • 这是在 Classic 和 Blue Ocean UI 中一切正常时的样子(众所周知,Blue Ocean UI 无法在并行运行中显示多个阶段,请参阅 JENKINS-38442):

    经典UI
    Classic UI - Build OK

    蓝海UI
    Blue Ocean UI - Build OK

    如果 Stage A,这是输出在 python:2.7.14失败:

    经典UI
    Classic UI - Failed Stage A step

    蓝海UI
    Blue Ocean UI - Failed Stage A step

    关于docker - 从单个 Jenkinsfile 运行多个 Docker 容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49782267/

    相关文章:

    docker - 使用 docker 代理了解 Jenkins 管道步骤

    Scala、Groovy、Clojure

    groovy - Groovy 如何解析带有空格的方法调用

    maven - 在 Jenkins 中配置 maven 设置

    grails - Grails 4.0无法将域保存到数据库

    docker - Nexus 3 作为 Traefik v.2 背后的 Docker Registry - 推送失败

    date - Docker 容器日期/时间与主机 PC 完全不同

    database - 如何在 Docker 中安装 Cassandra?

    docker - Prisma 在 jenkins 中随机找不到 docker 镜像

    jenkins - 如何列出 Jenkins 管道脚本中目录中的所有目录