简体   繁体   English

在Jenkins(在docker容器中)管道中构建docker镜像

[英]Build docker image in Jenkins (in docker container) pipeline

I use Jenkins from docker container. 我使用Docker容器中的Jenkins。 And I want to build docker image in Jenkins pipeline but docker is not exist in this container (where Jenkins). 我想在Jenkins管道中构建docker镜像,但这个容器(Jenkins)中不存在docker。

Jenkins container deployed by Docker Compose, yml file: 由Docker Compose部署的Jenkins容器,yml文件:

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

What we can do to build docker image in Jenkins pipeline? 我们可以做些什么来在Jenkins管道中构建docker镜像? Can we deploy some docker container with docker and use once for build docker image? 我们可以使用docker部署一些docker容器并使用一次构建docker镜像吗? or something else? 或者是其他东西? How do you doing with they? 你是怎么做的?

Edit: 编辑:

Thanks @VonC, I checked your information, but... "permission denied" 谢谢@VonC,我检查了你的信息,但......“许可被拒绝”

Docker Compose file: Docker撰写文件:

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: 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") 
                        //}

                    }
                }
            }
        }
    }
}

Result: 结果:

[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

Edit: Last problem with "permission denied" fixed with: 编辑:修正了“权限被拒绝”的最后一个问题:

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

Worked State: 工作状态:

Call in host: 致电主持人:

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

Docker Compose file: Docker撰写文件:

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: 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") 
                        //}

                    }
                }
            }
        }
    }
}

My resolve: 我的决心:

I add some step in Jenkinsfile and get: 我在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"
            }
        }
    }
}

You can look at " Docker in Docker in Jenkins pipeline ". 你可以看看“ Jenkins管道中的Docker Docker ”。 It includes the step: 它包括以下步骤:

inside the Jenkinsfile, I need to connect my build container to the outer Docker instance. 在Jenkinsfile中,我需要将构建容器连接到外部Docker实例。 This is done by mounting the Docker socket itself: 这是通过安装Docker插座本身来完成的:

docker.build('my-build-image').inside("--volume=/var/run/docker.sock:/var/run/docker.sock") {  
   // The build here
}

You can see a similar approach in " Building containers with Docker in Docker and Jenkins ". 您可以在“ 使用Docker和Jenkins中的Docker构建容器 ”中看到类似的方法。

In order to make the Docker from the host system available I need to make the API available to the Jenkins docker container. 为了使Docker能够从主机系统中获得,我需要将API提供给Jenkins docker容器。 You can do this by mapping the docker socket that is available on the parent system. 您可以通过映射父系统上可用的docker套接字来完成此操作。
I have created a small docker-compose file where I map both my volumes and the docker socket as following: 我创建了一个小的docker-compose文件,我将我的卷和docker socket映射如下:

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

Please note the special mapping the ' /var/run ' with rw privileges, this is needed to make sure the Jenkins container has access to the host systems docker.sock . 请注意特殊映射' /var/run '和rw权限,这是确保Jenkins容器可以访问主机系统docker.sock

And, as I mentioned before , you might need to run docker in privilege mode. 而且,正如我之前提到的 ,您可能需要在特权模式下运行docker。
Or, as the OP reported: 或者,正如OP报道的那样:

sudo chmod 0777 /var/run/docker.sock

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM