如何在容器中運行 Jenkins pipeline 任務

原文鏈接:https://www.cnblogs.com/sparkdev/p/8863773.html

持續集成中的 pipeline 技術和 docker 都是當前正在發展的主流方向,當然把它們結合起來在 CI/CD 過程中發揮出更強大的威力也是大家共同的目標。本文將介紹如何在 Jenkins pipeline 中集成使用 docker,好在當前的 Jenkins 已經默認通過插件實現了與 docker 的集成,所以這將是一段輕鬆愉快的旅程。

添加 linux 主機作爲 build agent

簡單起見,我們使用一臺安裝了 docker 的 linux 虛機,並通過 ssh 將其啓動爲 Jenkins server 的 build agent。主要操作步驟如下:

  • 在 linux 機器上創建一個用戶 jenkins, 密碼爲 123456
  • 創建目錄 /var/jenkins, 並把 owner 修改爲 jenkins
  • 安裝 jre,注意:必須安裝
  • 安裝 docker

我們通過下面的腳本一次搞定這些操作(docker 的安裝請參考官方文檔):

 

#!/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):

其中的 "Remote root directory" 就是剛纔創建的 /var/jenkins 目錄。"Launch method" 選擇 "Launch slave agents via SSH"。Host 爲 linux 虛機的 IP,Credentials 則爲剛纔創建的 jenkins 用戶。

運行簡單的 demo

先來運行一個簡單的 demo。創建一個 pipeline 類型的 job,並輸入下面的 pipeline script:

 

pipeline {
    agent {
        docker { image 'node:7-alpine' }
    }
    stages {
        stage('Test') {
            steps {
                sh 'node --version'
            }
        }
    }
}

 

運行該任務,執行結果如下:

 

[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] sh
[myjob] Running shell script
+ node --version
v7.10.1
[Pipeline] }
[Pipeline] // stage
[Pipeline] }

 

其中的命令 node --version 就是在容器中執行的。

通過 label 指定運行 stage 的 agent

Jenkins 默認會把任務分配給任何可用的 agent,如果我們要指定任務執行的 agent,可以在 docker 的配置中指定 label,這樣該任務只會被分配到具有某個 label 的 agent 上運行:

agent {
    docker {
        image 'node:7-alpine'
        label 'xxxxxx'
    }
}

在 Folder 級別指定 label 和 registry 信息

我們還可以在 folder 級別指定 label,這樣的設置會應用在 folder 內所有沒有設置 label 的任務上:

除了 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

通過指定 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 集成的已經很好了。當然你還可以實現更多更復雜的用例,趕緊動手吧!

參考:
Using Docker with Pipeline
Pipeline Syntax

作者:sparkdev

出處:http://www.cnblogs.com/sparkdev/

51reboot 的 python自動化運維課程9月22日開課

詳情添加小助手Amy  WeChat:17812796384

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章