持續集成中的 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 集成的已經很好了。固然你還能夠實現更多更復雜的用例,趕忙動手吧!