1. 授权认证
  2. 获取用户个人信息
  3. 项目协同
  4. 代码托管
  5. 持续集成
  6. 制品仓库
  7. 测试管理
  1. 项目协同
  2. 代码仓库
  3. DevOps 实践之旅
  4. 一分钟开始持续集成之旅
  5. 持续部署
  6. 制品库

在持续集成中使用 Docker

背景介绍

Docker 目前已经是一个非常普遍的工具。在 CODING 的持续集成当中,除了使用 Docker 作为持续集成的构建环境外,您可能经常需要以 Docker 的形式运行额外的服务作为测试依赖,或在持续集成过程中构建 Docker 镜像,并推送到相关的制品库。

关于如何使用 Docker 作为持续集成的构建环境,我们已有文章进行说明:《持续集成的构建环境》

运行指定 Docker 镜像并在容器内执行命令

在构建过程中,您可能会需要使用到公有的 Docker 镜像仓库,去拉取指定的镜像执行命令。

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                  script {
                    docker.image("ubuntu").inside('-e MY_ENV=123') {
                          sh 'echo ${MY_ENV}'
                    }     
                  }
            }
        }
    }
}

运行指定 Registry 的 Docker 镜像

在构建过程中,您可能会需要使用到私有的 Docker 镜像仓库,如:CODING 制品库所提供的 Docker 镜像仓库。

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                  script {
                    docker.withRegistry('https://registry.example.com') {

                        // 将会从从主机名 registry.example.com 拉取 my-custom-image
                        docker.image('my-custom-image').inside {
                            sh 'make test'
                        }
                    }
                  }
            }
        }
    }
}

若所配置的 registry 对拉取操作带有鉴权,需要您提供有效的凭证 ID。

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                  script {
                    docker.withRegistry('https://registry.example.com', 'my-credentials-id') {

                    }
                  }
            }
        }
    }
}

在持续集成过程中构建 Docker 镜像

pipeline {
    agent any
    stages {
        // 需要检出代码后,才可以使用代码仓库内的 Dockerfile
        stage('Checkout') {
            steps {
                checkout([
                    $class: 'GitSCM', 
                    branches: [[name: env.GIT_BUILD_REF]], 
                    userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]])
            }
        }
        stage('Build') {
            steps {
                script {
                    // 默认将使用根路径的 Dockerfile 进行构建
                    docker.build('my-docker-image:1.0.0')
                }
            }
        }
    }
}

如需为构建指定额外的参数, 如:使用指定目录的 Dockerfile:

pipeline {
    agent any
    stages {
        // 需要检出代码后,才可以使用代码仓库内的 Dockerfile
        stage('Checkout') {
            steps {
                checkout([
                    $class: 'GitSCM', 
                    branches: [[name: env.GIT_BUILD_REF]], 
                    userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]])
            }
        }
        stage('Build') {
            steps {
                script {
                    // 将使用 ./dockerfiles/Dockerfile.build 进行构建
                    docker.build('my-docker-image:1.0.0', '-f Dockerfile.build ./dockerfiles')
                }
            }
        }
    }
}

将 Docker 镜像推送到指定的 Registry

pipeline {
    agent any
    stages {
        // 需要检出代码后,才可以使用代码仓库内的 Dockerfile
        stage('Checkout') {
            steps {
                checkout([
                    $class: 'GitSCM', 
                    branches: [[name: env.GIT_BUILD_REF]], 
                    userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]
                ])
            }
        } 

        stage('Build') {
            steps {
                  script {
                      docker.build('my-docker-image:1.0.0')

                    docker.withRegistry('https://registry.example.com', 'my-credentials-id') {
                        docker.image('my-docker-image:1.0.0').push()                    
                    }
                  }
            }
        }
    }
}

使用 Docker 运行额外的服务作为测试依赖

在测试过程当中,您可以使用 Docker 来运行 MySQL 等服务可能作为测试依赖服务。

下述示例使用了两个容器,一个作为 MySQL 的服务,另一个提供执行环境 (使用 docker link 连接两个容器)

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                  script {
                    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
                        // 注意:这里 callback 的运行环境并不是上面运行的 mysql:5 环境内,而是运行 docker 的宿主机环境 

                        // 运行第二个 mysql 作为执行环境

                        docker.image('mysql:5').inside("--link ${c.id}:db") {
                          // 这里执行的命令都是在第二个运行的 mysql docker 容器内
                          // 等待 mysql 服务等待
                          sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
                        }

                        // callback 内容运行完毕后,mysql docker 容器将会自动 stop 和 rm 掉
                    }       
                  }
            }
        }
    }
}

同时运行多个容器作为测试的依赖服务

有时候您可能不止需要一个额外的服务作为测试依赖,可以使用嵌套的方式来运行多个服务。

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                  script {
                    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c1 ->
                        // 注意:这里 callback 的运行环境并不是上面运行的 mysql:5 环境内,而是运行 docker 的宿主机环境

                        docker.image('redis').withRun('') { c2 ->
                            // 注意:这里 callback 的运行环境并不是上面运行的 redis 环境内,而是运行 docker 的宿主机环境
                            sh 'docker ps'
                        } 
                    }       
                  }
            }
        }
    }
}

参考文档

如您还想进一步了解 Jenkins 当中使用 Docker 的配置方式,可以参考 Jenkins 官方文档:

上一篇使用凭据 ID 进行认证
最近更新
感谢反馈有用
感谢反馈没用