DevOps實戰(Docker+Jenkins+Git)

ThreeCode發表於2021-12-26

基於Docker+Jenkins+Git的CI/CD實戰

與上一篇隨筆:基於 Jenkins+Docker+Git 的CI流程初探 有所不同,該內容更偏向於實際業務的基礎需求。

有幾點需要注意:

  • 該實戰中沒有涉及到映象倉庫,所以略去了映象推送階段,可以參考基於 Jenkins+Docker+Git 的CI流程初探
  • 與上一篇對比,該實戰是基於外網伺服器進行的,所以加入了Jenkins自動觸發拉取程式碼以及傳送構建報告功能。
  • 實戰中的Jenkins也是基於docker執行,對於Jenkins資料持久化是通過VOLUME實現的。
  • 不再進行自建git程式碼倉庫,選擇使用Gitee管理程式碼。
  • 實驗環境均已提前準備完畢。

1、Jenkins啟動

docker run \
 -u root \
 -d \
 -p 8080:8080 \
 -p 50000:50000 \
 -v jenkins-data:/var/jenkins_home \
 -v /etc/localtime:/etc/localtime:ro \
 -v /var/run/docker.sock:/var/run/docker.sock \
 --restart=always \
 jenkinsci/blueocean

啟動後設定使用者與密碼

2、新建item

名稱:java-devops-demo

建立流水線

選擇儲存

Jenkins流水線工作流程:

  先定義一個流水線專案,指定專案的git位置

  流水線啟動

  a.先去git位置自動拉取程式碼

  b.解析拉取程式碼裡面的Jenkinsfile檔案

  c.按照Jenkinsfile指定的流水線開始加工專案

Jenkins重要的點

  1) jenkins的家目錄 /var/jenkins_home 已經被我們docker外部掛載了/var/lib/docker/volumes/jenkins-data/_data

  2)WORKSPACE(工作空間)=/var/jenkins_home/workspace/java-devops-demo每一個流水線專案,佔用一個資料夾位置

  3)BUILD_NUMBER=5;當前第幾次構建

  4)WORKSPACE_TMP(臨時目錄)=/var/jenkins_home/workspace/java-devops-demo@tmp 

3、定義Jenkinsfile與Dockerfile具體內容

Jenkinsfile部分是逐步測試,按階段寫成。

pipeline{
    //全部的CI/CD流程都需要在這裡定義
    //任何一個代理可用就可以執行
    agent any

    //定義一些環境資訊
    environment {
      WS = "${WORKSPACE}"
    }

    //定義流水線的加工流程
    stages{

        stage('環境檢查'){
            steps {
               sh 'printenv'
               echo "正在檢測基本資訊"
               sh 'java -version'
               sh 'git --version'
               sh 'docker version'
               sh 'pwd && ls -alh'
            }
        }

        //1、編譯 "abc"
        stage('maven編譯'){
            agent {
                docker {
                    image 'maven:3-alpine'
                    args '-v /var/jenkins_home/appconfig/maven/.m2:/root/.m2'
                    //docker run -v /var/jenkins_home/appconfig/maven/.m2:/root/.m2
                }
            }
            //要做的所有事情
            //jenkins不配置任何環境的情況下, 僅適用docker相容所有場景
            steps{
                echo "編譯..."
                sh 'pwd && ls -alh'
                sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true'
            }
        }
//2、打包
        stage('生成映象'){
            steps{
                sh 'pwd && ls -alh'
                sh 'docker version'
                sh 'docker build -t java-devops-demo .'
            }
        }

        //3、部署
        stage('部署'){
            steps{
                echo "部署..."
                sh 'docker rm -f java-devops-demo-dev'
                sh 'docker run -d -p 80:8080 --name java-devops-demo-dev java-devops-demo'
            }
        }

        //4、推送報告
        stage("傳送報告"){
            steps {
                //簡訊通知,購買api介面即可
//                 sh 'curl -i -k -X POST 'https://gyytz.market.alicloudapi.com/sms/smsSend?mobile=mobile&param=**code**%3A12345%2C**minute**%3A5&smsSignId=2e65b1bb3d054466b82f0c9d125465e2&templateId=908e94ccf08b4476ba6c876d13f084ad'  -H 'Authorization:APPCODE dddddddd''
                //REST API 所有都行
//                 sh 'curl '
                echo '準備傳送報告'
                emailext body: '''<!DOCTYPE html>
                <html>
                <head>
                <meta charset="UTF-8">
                <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次構建日誌</title>
                </head>

                <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
                    offset="0">
                    <table width="95%" cellpadding="0" cellspacing="0"  style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
                <h3>本郵件由系統自動發出,請勿回覆!</h3>
                        <tr>
                           <br/>
                            各位同事,大家好,以下為${PROJECT_NAME }專案構建資訊</br>
                            <td><font color="#CC0000">構建結果 - ${BUILD_STATUS}</font></td>
                        </tr>
                        <tr>
                            <td><br />
                            <b><font color="#0B610B">構建資訊</font></b>
                            <hr size="2" width="100%" align="center" /></td>
                        </tr>
                        <tr>
                            <td>
                                <ul>
                                    <li>專案名稱 : ${PROJECT_NAME}</li>
                                    <li>構建編號 : 第${BUILD_NUMBER}次構建</li>
                                    <li>觸發原因: ${CAUSE}</li>
                                    <li>構建狀態: ${BUILD_STATUS}</li>
                                    <li>構建日誌: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                                    <li>構建  Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li>
                                    <li>工作目錄 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
                                    <li>專案  Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
                                </ul>


                <h4><font color="#0B610B">最近提交</font></h4>
                <ul>
                <hr size="2" width="100%" />
                ${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
                </ul>
                詳細提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/>

                            </td>
                        </tr>
                    </table>
                </body>
                </html>''', subject: '${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次構建日誌', to: 'xxxxx@163.com'
            }
        }
    }
        //後置處理過程
        post {
          failure {
            echo "這個階段 完蛋了.... $currentBuild.result"
          }
          success {
            echo "這個階段 成了.... $currentBuild.result"
          }
        }
}

Dockerfile:

#這個也得有
FROM openjdk:8-jre-alpine
LABEL maintainer="xxxxxxx@qq.com"
#複製打好的jar包
COPY target/*.jar /app.jar
RUN  apk add -U tzdata; \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; \
echo 'Asia/Shanghai' >/etc/timezone; \
touch /app.jar;

ENV JAVA_OPTS=""
ENV PARAMS=""

EXPOSE 8080

ENTRYPOINT [ "sh", "-c", "java -Djava.security.egd=file:/dev/./urandom $JAVA_OPTS -jar /app.jar $PARAMS" ]

Jenkinsfile與Dockerfile均位於java-devops-jemo目錄下,由Jenkins從git倉庫拉取。

4、遠端構建觸發

期望效果: 遠端的github程式碼提交了,jenkins流水線自動觸發構建。 

實現條件:

  • 保證jenkins所在主機能被遠端訪問。
  • jenkins中遠端觸發需要許可權,我們應該使用使用者進行授權。
  • 配置gitee,webhook進行觸發。

實現過程:

1)進入流水線配置頁,填入身份驗證令牌

 2)遠端構建即使配置了gitee/github 的webhook,預設會403。我們應該使用使用者進行授權 

  a.建立一個使用者 (主介面>管理Jenkins>管理user>新建使用者)

  b.新建使用者後一定要重新登陸啟用一次,進入使用者列表>點選當前使用者名稱>設定

  c.生成一個apitoken (生成後立即複製,只出現一次)

3)碼雲端配置WebHooks,進入碼雲對應程式碼倉庫-配置-WebHooks-新增WebHook

URL配置格式:http://dk:使用者dk的apitoken@主機的公網ip:8080/job/java-devops-demo/build?token=身份驗證令牌

新增成功後可測試與Jenkins主機的連通性。

至此,當本地修改程式碼,git push提交到gitee/github後,Jenkins就能夠自動構建,構建成功即可檢視前端頁面的變化。

5、配置maven環境

(使用自定義agent的方式引入maven環境,利用多階段構建不同場景下的複雜環境)

1)安裝docker pipeline外掛

2)自定義agent(在stages內部)

3)配置maven加速(配置國內阿里雲)

把Maven的配置檔案放在jenkins-data裡面的某個位置。預設所有的可變配置項都推薦放在jenkins-home的位置,增強移植性。

4)快取必要jar包,下次構建無需下載

agent {
    docker {
        image 'maven:3-alpine' //用完就會殺掉
        args '-v /var/jenkins_home/appconfig/maven/.m2:/root/.m2'
        // 將jar包對映到宿主機上/var/jenkins_home/appconfig/maven/.m2目錄中
        // 也可以將jar包以資料卷方式掛載到宿主機
    }
}
注:jenkins不配置任何環境的情況下, 僅適用docker相容所有場景。
  • 臨時容器導致的問題(每個stage都會回到預設workspace,臨時容器產生的打包資料不能被利用)
    • 第一次檢出程式碼,預設在 /var/jenkins_home/workspace/【java-devops-demo】
    • 使用docker臨時agent的時候,每一個臨時容器執行又分配臨時目錄 /var/jenkins_home/workspace/java-devops-demo@2;預設就是workspace/java-devops-demo 的內容
    • 在臨時容器裡面 執行的mvn package命令,會在 /var/jenkins_home/workspace/java-devops-demo@2 進行工作 
    • package到了 /var/jenkins_home/workspace/java-devops-demo@2 位置
    • 進入下一步(stage)進行打包映象,又會回到 /var/jenkins_home/workspace/【java-devops-demo】(預設workspace)這個位置
    •  這個位置沒有執行過 mvn clean package ,所以沒有target。 預設的 工作目錄 沒有 target

     解決方法:在臨時容器內部切換到Jenkins的預設工作目錄,再進行maven打包。

6、郵件推送

使用郵件擴充套件外掛:Email Extension Plugin-2.71 (對於每個stage執行的任務成功與否可以通過後置執行post來進行感知)

系統管理>系統配置>配置管理員郵箱(系統管理員郵件地址)、SMTP服務相關及其他

 

  

下圖Use SMTP Authentication部分在高版本外掛中已不再支援

填寫完畢,可以通過傳送測試郵件進行測試。

上圖的郵件使用者的授權碼需要配置郵件傳送的認證許可權資訊

  1. 登入自己郵箱,開啟POP3/SMTP郵件服務
  2. 獲取到自己的授權碼(tlqhksolsmeodjad)
  3. 配置並測試好郵件傳送即可

郵件模板內容見Jenkinsfile中報告推送階段。

至此,開發提交程式碼後,將自動觸發構建過程,構建結束後傳送此次構建郵件報告如下:

相關文章