gitlab+docker+jenkins基於dockerfile持續集成


篇幅使用的組件docker,dockerfile,docker-compose,registry,jenkins,gitlab,釘釘通知,篇幅有限,有些未詳細寫到的東西可能需要大家自行摸索。

來介紹下這套自動發布的工作流程及搭建步驟,此文檔只為記錄及展示,為了篇幅不過長,docker,docker-compose,不做贅述,其余組件均使用docker運行,

初始環境:

  IP1 : 192.168.18.221,jenkins+gitlab+docker-registry

  IP2:192.168.18.222,web

  關閉selinux

  關閉防火牆

一,安裝docker(兩台機器都裝)

# step 1: 安裝必要的一些系統工具
yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加軟件源信息
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新並安裝Docker-CE
yum makecache fast
yum -y install docker-ce
# Step 4: 開啟Docker服務
systemctl start docker      
#這里還是添加下鏡像加速
vim /etc/docker/daemon.json

  {
  "registry-mirrors": ["https://8****lj0.mirror.aliyuncs.com"]
  }

二,安裝gtitlab

# 不加 tag 則默認為最新版本 latest
docker pull gitlab/gitlab-ce
#通常會將 GitLab 的配置 (etc) 、 日志 (log) 、數據 (data) 放到容器之外, 便於日后升級, 因此請先准備這三個目錄。
mkdir -p /srv/gitlab/config
mkdir -p /srv/gitlab/logs 
mkdir -p /srv/gitlab/data
#啟動運行gitlab
docker run --detach \
  --hostname gitlab.example.com \
  --publish 8443:443 --publish 8880:80 --publish 8222:22 \
  --name gitlab \
  --restart always \
  --volume /srv/gitlab/config:/etc/gitlab \
  --volume /srv/gitlab/logs:/var/log/gitlab \
  --volume /srv/gitlab/data:/var/opt/gitlab \
 --add-host code.shiji.com:192.168.18.221 \ --privileged=true \ gitlab/gitlab-ce:latest
#這里能成功訪問后就不做額外的配置了,注意修改下配置文件里面的默認訪問地址
#配置下nginx代理后的訪問地址 http://code.shiji.com (這里域名是使用的本地解析,當需要拉取代碼的時候必須要能解析這個域名,)

三,安裝jenkins(這里放上官方文檔  https://jenkins.io/zh/doc/pipeline/tour/deployment/)

#拉取鏡像(這里建議大家使用官方推介的鏡像)
docker pull  jenkinsci/blueocean:lts
#創建掛載目錄並修改權限
mkdir /home/jenkins 
#創建並運行 docker run \ -u root \ -d \ -p 8080:8080 \ -p 50000:50000 \ -v /home/jenkins:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ #如果需要在容器中運行docker命令,這條必須加上
--add-host code.shiji.com:192.168.18.221 \ #這里我給jenkins添加了一條本地解析
 --restart always \
--name jenkins \ jenkinsci/blueocean:latest
#在log中找到初始密碼
docker logs jenkins
#修改密碼后jenkins安裝部分完成
#訪問地址,http://192.168.18.221:8080
#備注,安裝完成記得安裝插件,這里用docker構建,需要安裝 CloudBees Docker Build and Publish

四,搭建registary私倉(需要把把代碼用dockerfile構建后上傳到私倉庫,然后web服務器在拉下來重構,如果希望便捷操作可以使用雲上的私人倉庫)

#拉取鏡像
docker pull registry
#創建registry鏡像存儲目錄
mkdir -p /data/registry
#創建啟動registry
docker run -d -p 5000:5000 --restart=always --name registry -v /data/registry:/var/lib/registry registry:latest
#修改web服務的docker配置文件daemon.json,添加http
vim /etc/docker/daemon.json
{
 "insecure-registries": ["http://192.168.18.221:5000"],
  "registry-mirrors": ["https://8****lj0.mirror.aliyuncs.com"]
}
#構建完成后registry地址 http://192.168.18.221:5000

五,配置持續集成,這里再次梳理下工作流程,開發人員提交代碼  --> 觸發gitlab鈎子   --jenkins拉取代碼構建  -->構建成功,推送鏡像至私倉  -->web服務器拉取私倉鏡像創建容器  -->通知用戶;當然,失敗的時候也會通知用戶。

  1,配置pipeline,

    我們在jenkins里創建一個名為多分支的流水線,並且配置好代碼倉,並且讓他每次自動檢出分支,以及檢出前后都清理工作目錄,其他選項使用默認即可,Build Configuration選擇jenkinsfile;

    

     注意:此處配置完成后,scan流水線時會自動從gtilab里識別jenkinsfile文件,

  2,配置jenkinsfile文件,語法參考  https://jenkins.io/zh/doc/book/pipeline/,這里直接放出這邊配置好的文件

pipeline {
  agent any
  parameters {
	 string(name:'BRANCH_FOR_BODY',defaultValue:"${BRANCH_NAME}",description:'parameters used by ding talk')     #此處的兩個參數是為了后面釘釘通知的時候使用,這里后面再說
	 string(name:'BUILD_URL_FOR_BODY',defaultValue:"${BUILD_URL}",description:'build uri for body')
  }
  stages {
    stage('Deploy-Production') {
      when {
        branch 'master'
      }
      steps {
        sh '''
         docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                      
        '''
        sh 'docker push ${DOCKER_IMAGE_NAME}:latest'      #這里選擇每次都推送為lastest標簽
        sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'    #同時刪除本地構建打好標簽的鏡像
      }
      post {                       #根據執行標記來決定處理內容
        success {
	      sh 'sh notice.sh "test生產環境鏡像推送成功通知" "nginx-test" "推送鏡像成功"  ${BRANCH_NAME} ${BUILD_URL}'     #此處的釘釘推送腳本最后會放出
        }
        failure{
	      sh 'sh notice.sh "test生產環境鏡像推送失敗通知" "nginx-test" "推送鏡像失敗"  ${BRANCH_NAME} ${BUILD_URL}'
        }
      }
    }
  }
  environment {
    DOCKER_DEPLOY_URI = 'http://nginx.test.shiji.com'                    #這里只是為了個人使用,此篇幅未用到
    DOCKER_IMAGE_NAME = '192.168.18.221:5000/test/nginx-test'            #鏡像名稱
    DOCKER_SERVICE_NAME = 'TestService'                     #項目名稱
  }
}

  3,在上面的步驟中我們在構建的時候使用了dockerfile,這里使用個簡單的nginx作為測試

FROM nginx
RUN echo 'This is the first version' > /usr/share/nginx/html/index.html

  4,接下來我們把dockerfile也上傳至代碼倉,這時構建當然是失敗的,因為后續的釘釘通知腳本還沒有上傳,

  

  查看輸出,可以看到鏡像已經上傳成功

  

   5,至此,持續構建算初步完成,放上釘釘推送信息的腳本,記得把tocken換成自己的,(注意新版本的釘釘機器人要加簽了)

gitAuthor=''
gitAuthor=`git show --stat | awk '$0~/Author/{print $2}'`
response=`curl -X POST -H 'Content-Type:application/json; charset=utf-8' \
-d '{"msgtype":"markdown",\
"markdown":{"title":"'$1'",\
"text":"## '$1'\n\n**項目名稱**:'$2'\n\n**提交人**:'$gitAuthor'\n\n**狀態**:'$3'\n\n**分支**:'$4'\\n\\n有關更多構建的過程、錯誤信息、單元測試覆蓋率報告請參照 [構建日志]('$5')"\
}}' https://oapi.dingtalk.com/robot/send?access_token=d7f17229b054200xxxxxxxxxxxxxxxxxxxx3204e4dee`
echo $response

  6,gitlab自動推送,自動構建

    1,在jenkins安裝gitlab插件,注意這里並不是哪個gitlabhook的插件

    

      &插件安裝成功后我們修改jenkinsfile增加tigger,關於tigger的語法,官方文檔和往上都給的不太詳細,這里如果想過濾分支等操作參考下這兩篇文章

      https://blog.51cto.com/ygqygq2/2461766

      http://www.eryajf.net/3298.html

      &放上修改完成的jenkinsfile   

pipeline {
  agent any
  parameters {
	 string(name:'BRANCH_FOR_BODY',defaultValue:"${BRANCH_NAME}",description:'parameters used by ding talk') 
	 string(name:'BUILD_URL_FOR_BODY',defaultValue:"${BUILD_URL}",description:'build uri for body')
  }
  triggers{
	gitlab( triggerOnPush: true,
			triggerOnMergeRequest: true,
            branchFilterType: "NameBasedFilter",
			includeBranchesSpec: "master,dev",
			secretToken: "028d848ab64f"
		)
  }
  stages {
    stage('Deploy-Production') {
      when {
        branch 'master'
      }
      steps {
        sh '''
         docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                   
        '''
        sh 'docker push ${DOCKER_IMAGE_NAME}:latest'
        sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'
      }
      post {  
        success {
	      sh 'sh notice.sh "test生產環境鏡像推送成功通知" "nginx-test" "推送鏡像成功"  ${BRANCH_NAME} ${BUILD_URL}'
        }
        failure{
	      sh 'sh notice.sh "test生產環境鏡像推送失敗通知" "nginx-test" "推送鏡像失敗"  ${BRANCH_NAME} ${BUILD_URL}'
        }
      }
    }
  }
  environment {
    DOCKER_DEPLOY_URI = 'http://nginx.test.shiji.com'
    DOCKER_IMAGE_NAME = '192.168.18.221:5000/test/nginx-test'
    DOCKER_SERVICE_NAME = 'TestService'
  }
}

     2,jenkins設置里添加倉庫(這里的tocken需要去gitlab里生成)

    

 

     3,gitlab項目里創建webhook

      

    4,最后提交一次測試效果(釘釘通知)

    

 

7,到這里為止算是初步完成了自動構建,接下來要說說自動發布了,我們已經把鏡像推送到了私倉,接下來只需要在應用服務器上執行命令構建就行,這里說說我們是怎么做的。

  應用服務器發布腳本,腳本使用compose發布,腳本執行也是放在Jenkins file里,(這里配置了兩條是為了后續的pipeline多分支),腳本接受兩個參數,一個名稱及標簽,標簽是為了多分支的pipeline准備的,后續再說。

       腳本:

tag="$2"
# test
if [ $1 == "test" ]
then

    cd /docker/compose/test
    pwd
    docker pull 192.168.18.221:5000/test/nginx-test:$tag

    docker-compose up -d test
    echo "success"

elif [ $1 == "test1" ]
then

    cd /docker/compose/test1
    docker pull 192.168.18.221:5000/test/nginx-test:$tag

    docker-compose up -d test2
    echo "success"

else 
    echo "no equal service"
fi

  jenkinsfile:(寫在setp階段執行,這里我們使用的是接口的方式,需要在應用服務器上寫個接口去執行上面的腳本,當然你也可以直接遠程執行腳本,過程就不在贅述)

steps {
        sh '''
         docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                   
        '''
        sh 'docker push ${DOCKER_IMAGE_NAME}:latest'
        sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'
     sh 'curl ${DOCKER_DEPLOY_URI}/staging?service=${DOCKER_SERVICE_NAME}' #請求接口去執行上面的腳本發布,接口怎么寫的這里我就不放出來了,大家可以省略這一步直接遠程執行腳本(要配置ssh互信)
} 

最后:多分支pipeline

  上面內容設置了一些變量,就是為此准備的,在這里我們可以對應環境分成多個流水線分支,主要還是修改jenkinsfile:

pipeline {
  agent any
  parameters {
     string(name:'BRANCH_FOR_BODY',defaultValue:"${BRANCH_NAME}",description:'parameters used by ding talk') 
     string(name:'BUILD_URL_FOR_BODY',defaultValue:"${BUILD_URL}",description:'build uri for body')
  }
  triggers{
    gitlab( triggerOnPush: true,
            triggerOnMergeRequest: true,
            branchFilterType: "NameBasedFilter",
            includeBranchesSpec: "master,dev",
            secretToken: "028d848ab64f"
        )
  }
  stages {
    stage('Deploy-Production') {
      when {
        branch 'master'
      }
      steps {
        sh '''
         docker build -t ${DOCKER_IMAGE_NAME}:latest -f Dockerfile .                                   
        '''
        sh 'docker push ${DOCKER_IMAGE_NAME}:latest'
        sh 'docker rmi ${DOCKER_IMAGE_NAME}:latest'
        sh 'curl ${DOCKER_DEPLOY_URI}/staging?service=${DOCKER_SERVICE_NAME}&tags=latest'
      }
      post {  
        success {
          sh 'sh notice.sh "test生產環境鏡像推送成功通知" "nginx-test" "推送鏡像成功"  ${BRANCH_NAME} ${BUILD_URL}'
        }
        failure{
          sh 'sh notice.sh "test生產環境鏡像推送失敗通知" "nginx-test" "推送鏡像失敗"  ${BRANCH_NAME} ${BUILD_URL}'
        }
      }
    }
    stage('Deploy-Dev') {
      when {
        branch 'dev'
      }
      steps {
        sh '''
        docker build -t ${DOCKER_IMAGE_NAME}:dev -f Dockerfile .
        '''
        sh 'docker push ${DOCKER_IMAGE_NAME}:dev'
        sh 'docker rmi ${DOCKER_IMAGE_NAME}:dev'
        sh 'curl ${DOCKER_DEPLOY_URI}/dev?service=${DOCKER_SERVICE_NAME}&tags=dev'
      }
      post {
        success {
          sh 'sh notice.sh "test測試環境部署成功通知" "nginx-test" "成功"  ${BRANCH_NAME} ${BUILD_URL}'
        }
        failure{
          sh 'sh notice.sh "test測試環境部署失敗通知" "nginx-test" "失敗"  ${BRANCH_NAME} ${BUILD_URL}'
        }
      }
    } 
  }
  environment {
    DOCKER_DEPLOY_URI = 'http://dockerup.test.shiji.com'
    DOCKER_IMAGE_NAME = '192.168.18.221:5000/test/nginx-test'
    DOCKER_SERVICE_NAME = 'TestService'
  }
}

 

  最后效果

    jenkins:

  

 

  釘釘通知:(這里在實際的生產環境中,並沒有持續部署,所以通知是有區別的)

   

 

寫在最后:這篇是使用dockerfile的持續集成,當然還有其他方式,上面文中的連接作了更詳細的講解,各位看官如果能看到最后,歡迎留言指出文中不足的地方。


免責聲明!

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



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