Jenkins:从与代理运行的阶段(另一个Docker容器)连接到Docker容器

时间:2019-09-04 09:23:36

标签: docker jenkins jenkins-pipeline jenkins-declarative-pipeline

我正在重新构造管道以使用声明性管道方法,以便在每个阶段都可以to use Docker images

目前,我有以下工作代码,它们执行集成测试,以连接到在Docker容器中运行的数据库。

node {
    // checkout, build, test stages...
    stage('Integration Tests') {            
        docker.image('mongo:3.4').withRun(' -p 27017:27017') { c ->
        sh "./gradlew integrationTest"
    }
}

现在使用声明性管道,相同的代码看起来像这样:

pipeline {
    agent none
    stages {
        // checkout, build, test stages...
        stage('Integration Test') {
            agent { docker { image 'openjdk:11.0.4-jdk-stretch' } }
            steps {
                script {
                    docker.image('mongo:3.4').withRun(' -p 27017:27017') { c ->
                        sh "./gradlew integrationTest"
                    }
                }
            }
        }
    }
}

问题::该阶段现在在Docker容器内运行,运行docker.image()会导致该阶段出现docker: not found错误(它正在{{1 }}现在使用的图片。

问题:如何在声明式管道的某个阶段启动数据库容器并与其连接?

4 个答案:

答案 0 :(得分:2)

您实质上要使用的是DIND。

您正在使用的詹金斯奴隶实际上是使用docker agent { docker { image 'openjdk:11.0.4-jdk-stretch' } }

创建的

容器运行后,您将尝试执行docker命令。错误docker: not found有效,因为未安装docker cli。您需要更新dockerfile /创建安装了openjdk:11.0.4-jdk-stretch和docker dameon的自定义映像。

安装完守护程序后,您需要批量挂载/var/run/docker.sock,以便该守护程序通过套接字与主机docker守护程序对话。

该用户应该是root用户或特权用户,以避免权限被拒绝的问题。

答案 1 :(得分:1)

因此,如果我正确理解了,您的测试需要做两件事:

  • Java环境
  • 数据库连接

在这种情况下,您是否尝试过类似Docker In Docker (DIND)的其他方法?

在可以使用docker:dind作为基础图像并包含Java环境并在agent部分中使用它的自定义图像的情况下,其余的管道步骤将能够使用docker如您所愿。

答案 2 :(得分:0)

在您的示例中,您尝试在openjdk:11.0.4-jdk-stretch中运行一个容器。如果此映像未安装docker daemon,则将无法执行docker,但在这种情况下,它将在docker内部运行您不应该运行的docker。

所以这取决于您何时想要。

  • 使用多个容器: 在这种情况下,您可以合并多个docker映像,但是它们彼此之间不依赖:

    pipeline {
    agent none
    stages {
        stage('Back-end') {
            agent {
                docker { image 'maven:3-alpine' }
            }
            steps {
                sh 'mvn --version'
            }
        }
        stage('Front-end') {
            agent {
                docker { image 'node:7-alpine' }
            }
            steps {
                sh 'node --version'
            }
        }
    }
    

    }

  • 运行“ sidecar”容器: 此示例显示您同时使用两个容器,它们将能够彼此交互:

    node {
    checkout scm
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
        docker.image('mysql:5').inside("--link ${c.id}:db") {
            /* Wait until mysql service is up */
            sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
        }
        docker.image('centos:7').inside("--link ${c.id}:db") {
            /*
             * Run some tests which require MySQL, and assume that it is
             * available on the host name `db`
             */
            sh 'make check'
        }
    }
    

    }

请参考官方文档-> https://jenkins.io/doc/book/pipeline/docker/

希望它能对您有所帮助。

答案 3 :(得分:0)

我遇到了类似的问题,我希望能够使用现成的Maven Docker映像来运行我的构建,同时还能够构建包含该应用程序的Docker映像。 通过首先启动要在其中运行构建的Maven容器,使它可以访问主机Docker端点,来完成此任务。
部分示例:

docker run -v /var/run/docker.sock:/var/run/docker.sock maven:3.6.1-jdk-11

然后,在构建容器中,我下载Docker二进制文件并设置Docker主机:

export DOCKER_HOST=unix:///var/run/docker.sock
wget -nv https://download.docker.com/linux/static/stable/x86_64/docker-19.03.2.tgz
tar -xvzf docker-*.tgz
cp docker/docker /usr/local/bin

现在,我可以在build-container中运行docker命令。 对我来说,积极的一点是,在构建的一个步骤中在容器中构建的任何Docker镜像都将对构建的后续步骤(也将在容器中运行)可用,因为它们将保留在主机中。