持续集成中的 pipeline 技术和 docker 都是当前正在发展的主流方向,固然把它们结合起来在 CI/CD 过程当中发挥出更强大的威力也是你们共同的目标。本文将介绍如何在 Jenkins pipeline 中集成使用 docker,好在当前的 Jenkins 已经默认经过插件实现了与 docker 的集成,因此这将是一段轻松愉快的旅程。html
简单起见,咱们使用一台安装了 docker 的 linux 虚机,并经过 ssh 将其启动为 Jenkins server 的 build agent。主要操做步骤以下:node
咱们经过下面的脚本一次搞定这些操做(docker 的安装请参考官方文档):linux
#!/bin/bash # run this script like this: sudo ./addsudouser.sh useradd -m jenkins -d /home/jenkins -s /bin/bash; echo 'jenkins:123456' | sudo chpasswd usermod -a -G sudo jenkins; usermod -a -G docker jenkins; echo 'jenkins ALL=(ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers; sudo mkdir /var/jenkins sudo chown jenkins /var/jenkins sudo apt-get -y install default-jre
在 linux 虚机上执行上面的脚本,而后在 Jenkins 中添加 node(build agent):git
其中的 "Remote root directory" 就是刚才建立的 /var/jenkins 目录。"Launch method" 选择 "Launch slave agents via SSH"。Host 为 linux 虚机的 IP,Credentials 则为刚才建立的 jenkins 用户。github
先来运行一个简单的 demo。建立一个 pipeline 类型的 job,并输入下面的 pipeline script:docker
pipeline { agent { docker { image 'node:7-alpine' } } stages { stage('Test') { steps { sh 'node --version' } } } }
运行该任务,执行结果以下:shell
[Pipeline] { [Pipeline] stage [Pipeline] { (Test) [Pipeline] sh [myjob] Running shell script + node --version v7.10.1 [Pipeline] } [Pipeline] // stage [Pipeline] }
其中的命令 node --version 就是在容器中执行的。bash
Jenkins 默认会把任务分配给任何可用的 agent,若是咱们要指定任务执行的 agent,能够在 docker 的配置中指定 label,这样该任务只会被分配到具备某个 label 的 agent 上运行:app
agent { docker { image 'node:7-alpine' label 'xxxxxx' } }
咱们还能够在 folder 级别指定 label,这样的设置会应用在 folder 内全部没有设置 label 的任务上:ssh
除了 label,还能够设置 docker registry URL 及其身份认证的凭据。
咱们还能够在不一样的 stage 中运行不一样的容器,其实就是每一个 stage 用本身的容器镜像建立容器并执行任务,stage 之间没啥关系:
pipeline { agent none stages { stage('Back-end') { agent { docker { image 'appropriate/curl' } } steps { sh 'curl www.google.com' } } stage('Front-end') { agent { docker { image 'node:7-alpine' } } steps { sh 'node --version' } } } }
经过指定 Dockerfile 文件,在 build agent 上直接构建容器镜像,而后生成容器并执行命令。下面的 demo 中咱们经过 Dockerfile 建立一个包含 curl 工具的容器镜像,而后经过该镜像启动容器并执行 HTTP 请求。该 demo 一共包含三个文件:Dockerfile 、entrypoint.sh 和 Jenkinsfile,你们能够直接从这里下载它们。先看一下 Dockerfile 文件的内容:
FROM alpine:latest RUN apk add --update curl && rm -rf /var/cache/apk/* COPY entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] CMD ["curl"]
其中的 entrypoint.sh 内容以下:
#!/bin/sh set -e # Prepend "curl" if the first argument is not an executable if ! type -- "$1" &> /dev/null; then set -- curl "$@" fi exec "$@"
Jenkinsfile 的内容以下:
pipeline { agent { dockerfile { filename 'Dockerfile' dir 'curl' label 'docker' } } stages { stage('Test') { steps { sh 'curl http://www.cnblogs.com/sparkdev/p/8795141.html' } } } }
注意,该文件中咱们设置了 dir 为 curl 目录,这是由于此项目的 Dockerfile 文件不是在代码库的根目录下,因此须要指定其相对目录的路径。
而后在 Jenkins 中建立 pipeline 类型的 job,并把 pipeline 的 Definition 设置为 "Pipeline script from SCM" 。接下来设置好代码仓库的路径就能够了。运行该任务,从日志上能够看到取完代码后先经过 Dockerifle 文件构建了容器镜像:
并在容器中运行了 curl http://www.cnblogs.com/sparkdev/p/8795141.html 命令。
上面的例子中咱们经过 Dockerfile 生成了容器镜像,而且完成了相关的测试(经过 curl 请求了测试网页)。接下来就是把生成的容器镜像推送到镜像仓库中。下面将演示如何在 pipeline 中把构建的镜像推送的镜像仓库。首先在 Folder 的配置界面中添加访问 dockerhub.com 凭据以下:
若是是访问 dockerhub 就不须要填写 "Docker registry URL"。而后添加下面的 Pipeline script:
node { checkout([$class: 'GitSCM', branches: [[name: '*/master']], userRemoteConfigs: [[url: 'https://github.com/sparkdevo/ctools.git']]]) docker.withRegistry('', '9e70c1eb-814c-4cf2-97e9-5bfc20461231') { def customImage = docker.build("ljfpower/curl:${env.BUILD_ID}","./curl") customImage.inside { sh 'curl http://www.cnblogs.com/sparkdev/p/8795141.html' } customImage.push() customImage.push('latest') } }
注意, 9e70c1eb-814c-4cf2-97e9-5bfc20461231 刚才建立的凭据的 ID,能够从 folder 的 Credentials 界面中得到。运行这个任务,执行成功后去 dockerhub.com 上看一下,是否是已经把新构建的镜像推送上去了:
从本文的几个简单 demo 能够看出,jenkins pipeline 和 docker 集成的已经很好了。固然你还能够实现更多更复杂的用例,赶忙动手吧!