从Jenkins中的容器访问父守护程序

时间:2019-01-16 17:10:07

标签: docker jenkins

我们在詹金斯(Jenkins)有很多节点在运行我们的工作。我需要根据詹金斯的工作来制作两个图像。为此,我读到您应该使用绑定安装来共享unix套接字,而我这样做是这样的:

agent {
    docker {
        image 'custom-alpine-with-docker'
        args '-v /var/run/docker.sock:/var/run/docker.sock'
    }
}

然后我要按以下方式使用它:

stage('Build and push image(s)') {
    steps {
        dir("${WORKING_DIRECTORY}") {
            script {
                echo 'Building amd64 image'
                amd64image = docker.build("${IMAGE_NAME}:${BUILD_NUMBER}-amd64", "-f ./Dockerfile.amd64 .")
                echo 'Building arm32v7 image'
                arm32v7image = docker.build("${IMAGE_NAME}:${BUILD_NUMBER}-arm32v7", "-f ./Dockerfile.arm32v7 .")
            }
            script {
                docker.withRegistry("${DOCKER_REGISTRY_URL}", "${REPOSITORY_CREDENTIALS}") {
                    amd64image.push()
                    arm32v7image.push()
                }
            }
        }
    }
}

但是,在jenkins作业中发出构建命令后,我得到以下错误:

  

time =“ 2019-01-16T16:55:33Z” level = error msg =“无法拨打gRPC:无法连接到Docker守护程序。'docker daemon'是否在此主机上运行?:拨打unix / var /运行/docker.sock:连接:权限被拒绝”   17:56:59尝试连接到unix:///var/run/docker.sock上的Docker守护程序套接字时,获得的权限被拒绝:

一个简单的搜索显示此错误的根源是,试图访问该守护程序的用户不在docker组中,但我不了解这些组成员身份在共享这样的守护程序时如何工作。

如果我转到构建失败的节点,并检查docker组中的用户,则会得到以下信息:

$ getent group docker
docker:x:126:inst,jenkins

那么如何允许在该主机上的容器中运行的用户访问同一守护程序?

小更新

只需使用docker run -v /var/run/docker.sock:/var/run/docker.sock -ti docker在本地进行操作,当我在容器和主机上写入docker ps时,我就会看到相同的容器在运行。

在我的开发机器上获取所有用户,看起来像这样:

docker:x:999:overlord

所以我想我需要一些特殊的詹金斯解决方案才能使它起作用。

1 个答案:

答案 0 :(得分:0)

我认为我已经以令人满意的方式解决了这个问题。这是分步指南:

  1. 确保将docker安装在需要运行的容器中
  2. 创建docker组和jenkins用户:
CMD DOCKER_GID=$(stat -c '%g' /var/run/docker.sock) && \
    groupmod --gid ${DOCKER_GID} ${DOCKER_GROUP} && \
    usermod -a -G ${DOCKER_GROUP} ${JENKINS_USER} && \
    gosu jenkins sh

重要的是要注意,这里我获取了运行docker的基础系统的组ID。因为我已经在容器中安装了docker并且该组已经存在,所以我修改了现有的组以匹配系统的组ID。最后,我将jenkins用户添加到docker组。运行后,您的/ etc / group在容器中应如下所示:

docker:x:999:jenkins

  1. 在您的管道中,如下所示启动代理:
agent {
    docker {
        image 'storemanager-build'
        args '-u root -v /var/run/docker.sock:/var/run/docker.sock'
    }
}

通过提供-u root标志,您可以覆盖詹金斯在使用声明性管道时强制您使用的用户jenkins。您必须使用root才能使CMD命令起作用并能够创建组。

运行映像时,该命令将切换到允许访问基础unix套接字的jenkins用户。

这是我的Jenkinsfile的摘录:

pipeline {

    agent {
        docker {
            image 'build-image'
            args '-u root -v /var/run/docker.sock:/var/run/docker.sock'
        }
    }

    stages {

        stage('Build jar') {
            steps {
                dir("${WORKING_DIRECTORY}") {
                    script {
                        if (isUnix()) {
                            sh './mvnw --batch-mode clean install'
                        } else {
                            bat 'mvnw.cmd --batch-mode clean install'
                        }
                    }
                }
            }
        }

        stage('Build and push image(s)') {
            steps {
                dir("${WORKING_DIRECTORY}") {
                    script {
                        amd64image = docker.build("${IMAGE_NAME}", "-f ./Dockerfile.amd64 .")
                        arm32v7image = docker.build("${IMAGE_NAME}", "-f ./Dockerfile.arm32v7 .")
                    }
                    script {
                        docker.withRegistry("${DOCKER_REGISTRY_URL}", "${STOREMANAGER_REPOSITORY_CREDENTIALS}") {
                            amd64image.push("${BUILD_NUMBER}-amd64")
                            arm32v7image.push("${BUILD_NUMBER}-arm32v7")
                        }
                    }
                }
            }
        }
    }

    post {
        always {
            sh "chmod -R 777 ." // Jenkins can't clean built resources without this as we run the container as root
            cleanWs()
        }
    }
}

帮助我的资源:

https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/ https://github.com/jenkinsci/docker/issues/196

希望这会有所帮助。

相关问题