在Jenkins中构建Docker镜像(在Docker容器中)的流水线

9

我是一名有用的助手,可以为您进行文本翻译。

我使用来自Docker容器的Jenkins。我想在Jenkins流水线中构建Docker镜像,但是该容器中不存在Docker(即Jenkins所在容器中没有安装Docker)。

Jenkins容器由Docker Compose部署,yml文件如下:

version: "3.3"
services:
  jenkins:
    image: jenkins:alpine
    ports:
      - 8085:8080
    volumes:
      - ./FOR_JENKINS:/var/jenkins_home

我们可以在Jenkins管道中构建Docker镜像。我们是否可以使用Docker部署某些Docker容器,并仅在构建Docker镜像时使用它们?还是其他方法?您如何处理这些问题? 编辑: 感谢@VonC,我检查了您的信息,但是......“权限被拒绝”。
Docker Compose文件:
version: "3.3"
services:
  jenkins:
    image: jenkins:alpine
    ports:
      - 8085:8080
    volumes:
      - ./FOR_JENKINS:/var/jenkins_home
#      - /var/run/docker.sock:/var/run/docker.sock:rw
      - /var/run:/var/run:rw

Jenkinsfile:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo "Compiling..."
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt compile"
            }
        }
        /*stage('Unit Test') {
            steps {
                echo "Testing..."
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt coverage 'test-only * -- -F 4'"
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt coverageReport"
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt scalastyle || true"
            }
        }*/
        stage('DockerPublish') {
            steps {
                echo "Docker Stage ..."
                // Generate Jenkinsfile and prepare the artifact files.
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt docker:stage"

                echo "Docker Build-2 ..."
                // Run the Docker tool to build the image
                script {
                    docker.withTool('docker') {

                        echo "D1- ..."
                        //withDockerServer([credentialsId: "AWS-Jenkins-Build-Slave", uri: "tcp://192.168.0.29:2376"]) { 
                            echo "D2- ..."
                            sh "printenv" 
                            echo "D3- ..."
                            //sh "docker images" 
                            echo "D4- ..."
                            docker.build('my-app:latest', 'target/docker/stage').inside("--volume=/var/run/docker.sock:/var/run/docker.sock")
                            echo "D5- ..."
                            //base.push("tmp-fromjenkins") 
                        //}

                    }
                }
            }
        }
    }
}

结果:

[job1] Running shell script

+ docker build -t my-app:latest target/docker/stage

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.29/build?buildargs=%7B%7D&cachefrom=%5B%5D&cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&labels=%7B%7D&memory=0&memswap=0&networkmode=default&rm=1&shmsize=0&t=my-app%3Alatest&target=&ulimits=null: dial unix /var/run/docker.sock: connect: permission denied

script returned exit code 1

编辑: "权限被拒绝" 的最后一个问题已经得到解决,方法如下:

>>sudo chmod 0777 /var/run/docker.sock

工作状态:

呼入主持人:

>>sudo chmod 0777 /var/run/docker.sock

Docker Compose 文件:

version: "3.3"
services:
  jenkins:
    image: jenkins:alpine
    ports:
      - 8085:8080
    volumes:
      - ./FOR_JENKINS:/var/jenkins_home
#      - /var/run/docker.sock:/var/run/docker.sock:rw
      - /var/run:/var/run:rw

Jenkinsfile:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo "Compiling..."
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt compile"
            }
        }
        /*stage('Unit Test') {
            steps {
                echo "Testing..."
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt coverage 'test-only * -- -F 4'"
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt coverageReport"
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt scalastyle || true"
            }
        }*/
        stage('DockerPublish') {
            steps {
                echo "Docker Stage ..."
                // Generate Jenkinsfile and prepare the artifact files.
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt docker:stage"

                echo "Docker Build-2 ..."
                // Run the Docker tool to build the image
                script {
                    docker.withTool('docker') {

                        echo "D1- ..."
                        //withDockerServer([credentialsId: "AWS-Jenkins-Build-Slave", uri: "tcp://192.168.0.29:2376"]) { 
                            echo "D2- ..."
                            sh "printenv" 
                            echo "D3- ..."
                            //sh "docker images" 
                            echo "D4- ..."
                            docker.build('my-app:latest', 'target/docker/stage')
                            echo "D5- ..."
                            //base.push("tmp-fromjenkins") 
                        //}

                    }
                }
            }
        }
    }
}

我的决心:

我在Jenkinsfile中添加了一些步骤,结果得到了:

pipeline {
    agent any
    //def app

    stages {
        stage('Build') {
            steps {
                echo "Compiling..."
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt compile"
            }
        }

        stage('DockerPublish') {
            steps {
                echo "Docker Stage ..."
                // Generate Jenkinsfile and prepare the artifact files.
                sh "${tool name: 'sbt', type: 'org.jvnet.hudson.plugins.SbtPluginBuilder$SbtInstallation'}/bin/sbt docker:stage"

                echo "Docker Build ..."
                // Run the Docker tool to build the image
                script {
                    docker.withTool('docker') {

                            echo "Environment:"
                            sh "printenv" 
                            app = docker.build('ivanbuh/myservice:latest', 'target/docker/stage')
                            echo "Push to Docker repository ..."
                         docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials') {  
                                app.push("${env.BUILD_NUMBER}")
                                app.push("latest")
                            }

                            echo "Complated ..."
                    }
                }
            }
        }
//https://boxboat.com/2017/05/30/jenkins-blue-ocean-pipeline/
//https://gist.github.com/bvis/68f3ab6946134f7379c80f1a9132057a
        stage ('Deploy') {
            steps {
                sh "docker stack deploy myservice --compose-file docker-compose.yml"
            }
        }
    }
}

你是否以特权模式运行Docker?(https://github.com/rancher/jenkins-master#running-docker-server-within-docker) - VonC
好的,那么我想你的 chown 现在是一个不错的解决方法。我已经在答案中引用了它。 - VonC
我将尝试在Jenkins流水线中使用Docker步骤来添加root用户。 - Ivan Bukharin
在Jenkins流水线中,如果您将docker.run作为参数添加,则可以将其添加。我不太了解Docker Compose,但是查看文档后建议尝试添加以下内容:security_opt:
  • label:user:root
- yorammi
问题已经解决,描述在顶部“结果状态”。谢谢大家!你们帮了个大忙! - Ivan Bukharin
显示剩余4条评论
1个回答

7
你可以查看 "Jenkins管道中的Docker in Docker". 它包括以下步骤:
在Jenkinsfile中,我需要将我的构建容器连接到外部Docker实例。这可以通过挂载Docker套接字本身来完成:
docker.build('my-build-image').inside("--volume=/var/run/docker.sock:/var/run/docker.sock") {  
   // The build here
}

在 "使用Docker in Docker和Jenkins构建容器" 中,您可以看到类似的方法。

为了使来自主机系统的Docker可用,我需要将API提供给Jenkins Docker容器。您可以通过映射在父系统上可用的docker套接字来实现此目的。
我创建了一个小的docker-compose文件,其中我将我的卷和docker套接字映射如下:

jenkins:
  container_name: jenkins
  image: myjenkins:latest
  ports:
    - "8080:8080"
  volumes:
    - /Users/devuser/dev/docker/volumes/jenkins:/var/jenkins_home
    - /var/run:/var/run:rw

请注意特殊的映射,使用rw权限将“/var/run”与宿主系统的docker.sock连接起来,这是确保Jenkins容器可以访问宿主系统的docker.sock所必需的。
而且,就像我之前提到过的那样,您可能需要在特权模式下运行docker。
或者,正如OP报告的那样:
sudo chmod 0777 /var/run/docker.sock

我正在制作下一个方法,它将写在第一篇帖子中。 - Ivan Bukharin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接