使用Jenkins pipeline流水線構建docker鏡像和發布


新建一個pipeline job

選擇Pipeline任務,然后進入配置頁面。

對於Pipeline, Definition選擇 "Pipeline script from SCM".

需要注意的是Script Path, 這里要指定項目中Jenkinsfile文件的具體位置。默認是根目錄。我這里是maven的一個子模塊,所以嵌套一層。

項目中添加Jenkinsfile

關於Jenkinsfile可以查閱w3c翻譯整理的文檔: https://www.w3cschool.cn/jenkins/jenkins-qc8a28op.html

以下是我自己的Jenkinsfile,這里用作注釋和備忘

node('slave001') {


    stage('Prepare') {
        echo "1.Prepare Stage"
        checkout scm
        pom = readMavenPom file: 'location/pom.xml'
        docker_host = "docker.ryan-miao.com"
        img_name = "${pom.groupId}-${pom.artifactId}"
        docker_img_name = "${docker_host}/${img_name}"
        echo "group: ${pom.groupId}, artifactId: ${pom.artifactId}, version: ${pom.version}"
        echo "docker-img-name: ${docker_img_name}"
        script {
            build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
            if (env.BRANCH_NAME != 'master' && env.BRANCH_NAME != null) {
                build_tag = "${env.BRANCH_NAME}-${build_tag}"
            }
        }
    }

    stage('Test') {
        echo "2.Test Stage"
        sh "mvn test"
    }
    stage('Build') {
        echo "3.Build Docker Image Stage"
        sh "mvn package  -Dmaven.test.skip=true"
        sh "docker build -t ${docker_img_name}:${build_tag} " +
                " --build-arg SPRING_PROFILE=prod " +
                " --build-arg JAR_FILE=target/${pom.artifactId}-${pom.version}.jar " +
                " ./location/"
    }

    stage('Push') {
        echo "4.Deploy jar and Push Docker Image Stage"
        sh "mvn deploy -Dmaven.test.skip=true"
        sh "docker tag ${docker_img_name}:${build_tag} ${docker_img_name}:latest"
        sh "docker tag ${docker_img_name}:${build_tag} ${docker_img_name}:${pom.version}"
        withCredentials([usernamePassword(credentialsId: 'docker-register', passwordVariable: 'dockerPassword', usernameVariable: 'dockerUser')]) {
            sh "docker login -u ${dockerUser} -p ${dockerPassword} docker.ryan-miao.com"
            sh "docker push ${docker_img_name}:latest"
            sh "docker push ${docker_img_name}:${pom.version}"
            sh "docker push ${docker_img_name}:${build_tag}"
        }
    }

    //stash 'complete-build'

}

if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME == null) {
    timeout(time: 10, unit: 'MINUTES') {
        input '確認要部署線上環境嗎?'
    }
}


node('slave001'){
    stage('Deploy') {
        //unstash 'complete-build'
        echo "5. Deploy Stage"

        sh "sed -i 's/<IMG_NAME>/${img_name}:${build_tag}/' location/k8s.yaml"
        sh "sed -i 's/<BRANCH_NAME>/${env.BRANCH_NAME}/' location/k8s.yaml"
        sh "/data/opt/kubernetes/client/bin/kubectl apply -f ${WORKSPACE}/location/k8s.yaml --record"
    }

}

  • node('slave001') { 最外層必須是node節點,這里單獨制定運行的jenkins節點,通常不用指定,由jenkins master分配任務即可。這種寫法屬於Scripted Pipeline。
  • stage('Prepare') {} stage是一個階段的語法,括號里階段名稱。腳本從node開始,按順序向下執行。遇到的第一個stage就是第一個階段。
  • 使用echo xxxx來輸出文字,給出進度信息。
  • checkout scm 是Jenkins固定獲取代碼的方法,會輸出Check out from version control。
  • pom = readMavenPom file: 'location/pom.xml' 是讀取workspace下相對目錄的pom文件。這個需要Jenkins 安裝Pipeline Utility Steps插件。通過${pom.groupId}-${pom.artifactId}來獲取pom信息. 我的pom在子module location里。
  • docker_host = "docker.ryan-miao.com" 聲明一個全局的變量,如果只想在方法體 {}中使用,可以加def
  • ${docker_host} 變量可以通過這樣類似shell的方式獲取。
  • build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() 用來獲取git的commit id
  • Build階段執行docker命令打包,把我們的變量傳遞到Dockerfile. 我的Dockerfile同樣在子module location下。
  • withCredentials可以調用存儲在Jenkins里的憑證。這個需要安裝Credentials Binding Plugin.
  • input會產生一個交互式的按鈕,需要手動點擊通過才會繼續,否則暫停。這個只是暫停下一步,線程還在運行。所以,需要單獨提出node之外,再添加一個超時設置。參見“input” step blocks executor
  • stash暫存文件,參見官方文檔. 主要用來把這次build過程中的某個文件給暫存,只在本次build有效。本次不需要。
  • timeout 主要用來設置超時,參見官方文檔, 時間單位有: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS。這里等待用戶確認是否繼續,若超過10分鍾還沒有確認,則停止。

看起來,似乎完美的從代碼編譯,打包,構建docker鏡像,推送到倉庫,設置觸發了部署。但離真正生產方案還有距離。因為你不可能編譯結束就直接上生產。真實的流程應該是: checkout->build->test-> 部署到測試環境 -> 對測試環境的自動化測試 -> 部署到生產環境。

如何做到build once, deploy many

我這里的pipeline步驟里沒有多環境串聯部署。這里部署到測試環境了,如果測試通過之后,想要部署生產環境應該怎么下一步呢?想要手動點一下某個按鈕,就可以將部署在測試環境的這個版本的鏡像部署到prod。input顯然不滿足需求。

第一,記錄當前測試環境的鏡像id;第二,提供一個生產prod job,可以手動輸入鏡像id進行部署.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM