Jenkins多分支流水線+Docker部署SpringBoot聚合項目

Jenkins+gitlab+maven+jdk+docker部署springboot聚合項目

jenkins.jpg

最終效果圖

效果圖

目錄


編寫Jenkinsfile,Dockerfile,start.sh

1. 什么是Jenkinsfile
流水線語法
Jenkinsfile 是 Jenkins 2.x 核心特性 Pipeline(流水線)的腳本霞扬,由Groovy語言實現(xiàn)。Jenkinsfile一般是放在項目根目錄,隨項目一起受源代碼管理軟件控制钠署,無需像創(chuàng)建“自由風(fēng)格"(Jenkins FreeStyle)項目一樣哗戈,每次可能需要拷貝很多設(shè)置到新項目,提供了一些直接的好處:

  • Pipeline上的代碼審查/迭代
  • Pipeline的審計跟蹤
  • Pipeline的唯一真實來源玻佩,可以由項目的多個成員查看和編輯出嘹。

Pipeline支持:Declarative和Scripted Pipeline(聲明式和腳本式)兩種格式。兩者都支持建立Pipeline(流水線)咬崔,兩者都可以用于在Web UI中定義一個流水線Jenkinsfile税稼,將Jenkinsfile文件創(chuàng)建并檢查到源代碼控制庫中通常被認(rèn)為是最佳做法烦秩。

Declarative Pipeline (聲明式格式樣例)

pipeline {
    agent any 
    stages {
        stage('編譯構(gòu)建') { 
            steps {
                // 
            }
        }
        stage('測試') { 
            steps {
                // 
            }
        }
        stage('部署') { 
            steps {
                // 
            }
        }
    }
}

Scripted Pipeline(腳本式格式樣例)

node {  
    stage('編譯構(gòu)建') { 
        // 
    }
    stage('測試') { 
        // 
    }
    stage('部署') { 
        // 
    }
}

要動手啦

2. 編寫聲明式Jenkinsfile ; 使用文本編輯器(最好支持 Groovy 語法高亮顯示)
工作原理:自動獲取源代碼 ==> 編譯構(gòu)建 ==> 構(gòu)建并推送鏡像到Harbor ==>根據(jù)環(huán)境部署服務(wù)到服務(wù)器

pipeline {
    agent any
    environment {
        registryUrl= "192.168.1.110:5000"       #搭建docker私有倉庫(Harbor)或者 用DockerHub 或者用云平臺的“容器鏡像服務(wù)”
        registry_user= "xxx"
        registry_pass= "xxx"
        env=test       //"test" or "prod"        #選擇打包及發(fā)布的環(huán)境
    }
    options {
        timestamps()                    //設(shè)置在項目打印日志時帶上對應(yīng)時間
        disableConcurrentBuilds()       //不允許同時執(zhí)行流水線,被用來防止同時訪問共享資源等
        buildDiscarder(logRotator(numToKeepStr: '3'))   // 表示保留n次構(gòu)建歷史
    }

    //gitlab  webhook觸發(fā)器
    //聚合項目郎仆,代碼發(fā)生以下動作后只祠,所有子項目將被觸發(fā)構(gòu)建,可選擇使用(前提需要gitlab配置 webhook)
    //triggers{    //方法一,為All時
    //   gitlab( triggerOnPush: true,                       //代碼有push動作就會觸發(fā)job
    //       triggerOnMergeRequest: true,                   //代碼有merge動作就會觸發(fā)job
    //        branchFilterType: "All")          //為All時(只有符合條件的分支才會觸發(fā)構(gòu)建 “All/NameBasedFilter/RegexBasedFilter”)
    //}
    //triggers{    //方法二扰肌,為branchFilterType時
    //   gitlab( triggerOnPush: true,                       
    //       triggerOnMergeRequest: true,                  
    //        branchFilterType: "branchFilterType",          //為branchFilterType時
    //        includeBranchesSpec: "dev")      //基于branchFilterType值抛寝,輸入期望包括的分支的規(guī)則
    //}

    stages{
        stage('Print Message') {      //自動獲取代碼+打印信息
            steps {
                echo "workspace: ${WORKSPACE}  build_id: ${BUILD_ID}  branch(gitlab分支名): ${env.BRANCH_NAME}"        
                echo "registryUrl: ${registryUrl}"
           }
        }
        //此步驟在調(diào)試Jenkinsfile時可以注釋以便了解目錄結(jié)構(gòu)
        stage('Delete Workspace') {         //清理工作目錄
            steps {
                echo "清理工作目錄: ${WORKSPACE}"
                deleteDir()     //表示刪除當(dāng)前目錄(${WORKSPACE})下內(nèi)容,通常用在構(gòu)建完畢之后清空工作空間
            }
        }
        stage('Packaging projetc') {   //編譯構(gòu)建
            steps {
                echo 'mvn打包子項目'
                script {
                    sh 'source /etc/profile && mvn clean package -pl ${JOB_NAME%%/*} -am -amd -P${env} -Dmaven.test.skip=true'     //springboot maven 多模塊 jenkins 單獨打包子項目
                }
            }
        }
        stage('Build & Push Image to Harbor') {   //構(gòu)建曙旭、推送鏡像
            steps {
                echo '構(gòu)建盗舰,推送鏡像到docker鏡像倉庫'
                dir ('./') {       //指定工作目錄(默認(rèn)為${WORKSPACE})
                    script {
                        sh 'mv ${JOB_NAME%%/*}/Dockerfile  ./'
                        sh 'docker login  --username=${registry_user} --password=${registry_pass}   ${registryUrl}'
                        def app = docker.build('${registryUrl}/${JOB_NAME%%/*}:${env}')
                        app.push('${env}')
                        sh 'docker rmi ${registryUrl}/${JOB_NAME%%/*}:${env}'     //刪除jenkins本地新建的鏡像
                    }
                }
                //推送鏡像后,刪除工作空間除Jenkinsfile & start.sh以外所有文件
                sh '''rm -rf `ls | egrep -v '(Jenkinsfile|start.sh)'`'''
            }
        }

        stage('Deploy to the Target server') {  //部署
            //when {
            //    beforeAgent true
            //    branch "${env.BRANCH_NAME}"              //gitlab分支名稱
            //}
            steps {
                timeout(time: 40, unit: 'SECONDS') {    // 設(shè)置遠(yuǎn)程部署超過40秒桂躏,將終止該步驟
                //部署到${env}環(huán)境
                sh 'bash ./start.sh ${JOB_NAME%%/*} ${registryUrl}/${JOB_NAME%%/*}:${env} ${env}'    //位置變量1:工程名字  钻趋; 位置變量2:鏡像名字  ; 位置變量3:指定環(huán)境
                }
            }            
        }

    }
}

3. 編寫Dockerfile

FROM java:latest
LABEL maintainer="qiujt <qiujt123@163.com>"
WORKDIR /data/logs
ADD canfu-admin/target/canfu-admin-0.0.1-SNAPSHOT.jar     canfu-admin.jar
EXPOSE  8091
ENTRYPOINT    ["java","-jar","-Xms512m","-Xmx1024m","-XX:PermSize=512M","-XX:MaxPermSize=1024M","/canfu-admin.jar"]
  • FROM 指定基礎(chǔ)鏡像剂习,并且必須是第一條指令爷绘。(可以選擇更小的鏡像openjdk:8-jdk-alpine,不過一些后臺項目驗證碼圖片會出不來进倍,慎用)
  • LABEL MAINTAINER 指定維護(hù)者信息 語法:LABEL maintainer=" user_name <user_email>"
  • WORKDIR:指定在創(chuàng)建容器后土至,終端默認(rèn)登陸進(jìn)來的工作目錄,一個落腳點
  • ADD 將宿主機(jī)目錄下的文件拷貝進(jìn)鏡像且 ADD 命令會自動處理 URL 和解壓 tar 壓縮包
  • EXPOSE 當(dāng)前容器對外暴露出的端口
  • ENTRYPOINT:指定一個容器啟動時要運行的命令猾昆,ENTRYPOINT 的目的和 CMD 一樣陶因,都是在指定容器啟動程序及參數(shù)

4. 編寫部署腳本(start.sh)

#/bin/bash
#ENV
 #docker私有倉庫(Harbor)
  registryUrl=192.168.1.110:5000
  registry_user="xxx"
  registry_pass="xxx"
  project_name=$1
  image_name=$2
  env=$3
  node_user=root
if [ "${env}"  == test ];then
   #測試環(huán)境
  node1=192.168.1.105
elif [ "${env}" == prod ];then
  #生產(chǎn)環(huán)境
  node1=192.168.1.106
else
    echo '沒有${env}環(huán)境!4刮稀楷扬!'
fi
  
#Prepare
echo "project_name: $1 , image_name: $2 , env:$3"

#Deploying
    #可以寫成一個ssh"",為了解析方便贴见,切分開(接下來為第一行烘苹,以此類推)
    ssh $node_user@$node1 "docker login --username=${registry_user} --password=${registry_pass} ${registryUrl} “
    ssh $node_user@$node1 "docker pull $image_name && docker rm -f $project_name || true "
    ssh $node_user@$node1 "docker run -itd --name=$project_name --restart=always  --net=host  -e TZ="Asia/Shanghai"  -v /data/logs/$project_name:/data/logs/$project_name $image_name"
    ssh $node_user@$node1 "docker image prune -a -f --filter 'until=1h' "
    ssh $node_user@$node1 "tailf /data/logs/$project_name/${project_name}.log || true"
  • (第一個ssh解析)登錄docker私有倉庫(Harbor)

  • 服務(wù)器拉取對應(yīng)鏡像;判斷容器是否存在片部,如果存在就結(jié)束容器,否則跳過

  • 基于鏡像創(chuàng)建容器镣衡。
    --restart=always:當(dāng) Docker進(jìn)程重啟后,容器自動啟動档悠;
    --net=host:指定容器網(wǎng)絡(luò)模式為host廊鸥,即容器暴露的端口,宿主機(jī)就是什么端口辖所;
    -e TZ="Asia/Shanghai" :定義容器使用時區(qū)惰说;
    -v:將子項目日志目錄從容器里映射到宿主機(jī)(視個人項目情況變更)。

  • 刪除1小時前拉取的缘回、并且未被使用的鏡像

  • 打印服務(wù)輸出日志吆视,輸出到j(luò)enkins控制臺

  • 補(bǔ)充:由于Pipeline(流水線)需要在目標(biāo)服務(wù)器(例如:192.168.1.105)上執(zhí)行操作典挑,因此需要通過ssh連接。
    (1)首先需要在Jenkins容器里面生成ssh的公鑰密鑰啦吧;

docker exec -it jenkins /bin/bash -c 'ssh-keygen -C "root@jenkins"'

(2)然后自行復(fù)制jenkins容器的公鑰(/root/.ssh/id_rsa.pub)文件內(nèi)容到目標(biāo)服務(wù)器的/root/.ssh/authorized_keys文件中搔弄。
注意第一次連接目標(biāo)服務(wù)器會提示一個交互動作(提示輸入“yes”或者“no”繼續(xù)操作)

[root@tools-env-101 ~]# docker exec -it jenkins /bin/bash -c "ssh 192.168.1.105"
The authenticity of host '192.168.1.105 (192.168.1.105)' can't be established.
ECDSA key fingerprint is SHA256:/2CklRXsExQNpBUr08qN6jqbx6wBkYceC/IShzwAemk.
Are you sure you want to continue connecting (yes/no)?    #提示輸入“yes”或者“no”繼續(xù)操作

要避開這個交互操作有兩種方式:
第一種將目標(biāo)服務(wù)器/etc/ssh/ssh_config里面的“StrictHostKeyChecking ask”改為“StrictHostKeyChecking no”,重啟ssh服務(wù)即可丰滑;
第二種直接執(zhí)行以下命令顾犹,交互輸入yes即可。

docker exec -it jenkins /bin/bash -c "sed -i '/192.168.1.105/d' /root/.ssh/known_hosts"
docker exec -it jenkins /bin/bash -c "ssh 192.168.1.105"   #輸入yes

創(chuàng)建多分支流水線項目

SpringBoot聚合項目比起傳統(tǒng)復(fù)雜的單體工程褒墨,使用Maven的多模塊配置炫刷,可以幫助項目劃分模塊,鼓勵重用郁妈,防止POM變得過于龐大浑玛,方便某個模塊的構(gòu)建,而不用每次都構(gòu)建整個項目噩咪,并且使得針對某個模塊的特殊控制更為方便 顾彰。
Jenkinsfile ,Dockerfile , start.sh位置關(guān)系胃碾;及子項目下創(chuàng)建各個環(huán)境文件(application-test.yml 和 application-prod.yml)


Springboot聚合項目

指定環(huán)境文件

創(chuàng)建jenkins流水線項目

配置流水線項目

點擊 “立刻掃描 多分支流水線”涨享,Jenkins掃描源碼地址每個分支,如果該分支下有Jenkinsfile仆百,那么就會創(chuàng)建一個分支Job
(自定義release-test為測試分支厕隧,release-3.1-prod為生產(chǎn)分支)
(注意的是,維護(hù)源碼時俄周,需要構(gòu)建的分支才加上Jenkinsfile吁讨,不然Jenkins會將帶有Jenkinsfile的分支也創(chuàng)建一個分支job,會顯得凌亂峦朗。例如:下圖的release-prod & release_eat_away & release_eat_away_dev)


掃描

到此建丧,多分支流水線項目配置完畢,可以點擊觸發(fā)構(gòu)建項目了
實際開發(fā)中波势,SpringBoot聚合項目往往只會頻繁的構(gòu)建其中的幾個子項目翎朱,不必每次都構(gòu)建整個項目,因此我把Jenkinsfile里面的觸發(fā)構(gòu)建的代碼注釋了艰亮。需要構(gòu)建時闭翩,找到對應(yīng)項目,對應(yīng)分支點擊構(gòu)建即可迄埃,也是很方便的。當(dāng)然大家有什么高效的方法兑障,懇請私信發(fā)我侄非,抱拳=锻簟!逞怨!

觸發(fā)構(gòu)建

點擊“打開 Blue Ocean”者疤,可以看到項目構(gòu)建的每個階段輸出日志

查看日志

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市叠赦,隨后出現(xiàn)的幾起案子驹马,更是在濱河造成了極大的恐慌,老刑警劉巖除秀,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糯累,死亡現(xiàn)場離奇詭異,居然都是意外死亡册踩,警方通過查閱死者的電腦和手機(jī)泳姐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暂吉,“玉大人胖秒,你說我怎么就攤上這事∧降模” “怎么了阎肝?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肮街。 經(jīng)常有香客問我盗痒,道長,這世上最難降的妖魔是什么低散? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任俯邓,我火速辦了婚禮,結(jié)果婚禮上熔号,老公的妹妹穿的比我還像新娘稽鞭。我一直安慰自己,他們只是感情好引镊,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布朦蕴。 她就那樣靜靜地躺著,像睡著了一般弟头。 火紅的嫁衣襯著肌膚如雪吩抓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天赴恨,我揣著相機(jī)與錄音疹娶,去河邊找鬼。 笑死伦连,一個胖子當(dāng)著我的面吹牛雨饺,可吹牛的內(nèi)容都是我干的钳垮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼额港,長吁一口氣:“原來是場噩夢啊……” “哼饺窿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起移斩,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肚医,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后向瓷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肠套,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年风罩,在試婚紗的時候發(fā)現(xiàn)自己被綠了糠排。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡超升,死狀恐怖入宦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情室琢,我是刑警寧澤乾闰,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站盈滴,受9級特大地震影響涯肩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巢钓,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一病苗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧症汹,春花似錦硫朦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞒斩,卻和暖如春破婆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胸囱。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工祷舀, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓蔑鹦,卻偏偏與公主長得像夺克,于是被迫代替她去往敵國和親箕宙。 傳聞我的和親對象是個殘疾皇子嚎朽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 在日常開發(fā)中,經(jīng)常會有發(fā)布的需求柬帕,而且經(jīng)常會碰到各種環(huán)境哟忍,比如:開發(fā)環(huán)境、測試環(huán)境陷寝、生產(chǎn)環(huán)境锅很。雖然可以使用手...
    tinylk閱讀 38,759評論 34 77
  • 前言 Jenkins就不用做多余的介紹了,作為CI/CD首選的開源解決方案凤跑,持續(xù)集成 (Continous Int...
    王奧OX閱讀 3,125評論 1 13
  • 又見煉樹 我不記得那是幾歲的時候爆安,都是童年的故事了。 小時候能夠玩的玩具很少仔引,我也沒有什么小伙伴扔仓,家里有三個弟弟,...
    我是一只狐閱讀 779評論 0 0
  • 太陽藏在了云彩后面咖耘,一早上還滴了幾滴小雨翘簇,大早上出門還讓人感覺涼涼的,新的一月儿倒,新的一天版保,恰逢周末,在這個新的開學(xué)...
    cc08閱讀 145評論 0 0
  • 七律·三顧朱家角古鎮(zhèn) @鐵山青士(笑獨行)[詩] 淀湖邊角再三游夫否, 所為何來慮不周彻犁。 感晚憶初堂表會, 浮光倒影飯...
    笑獨行閱讀 975評論 6 11