基於docker-compose的Gitlab CI/CD實踐&排坑指南

引言

         看過docker-compose真香的園友可能留意到當時是【把部署dll文件拷貝到生產機器】,即時打包成鏡像並啓動容器,並無完成CI/CD。html

         通過長時間實操驗證,終於完成基於Gitlab的CI/CD實踐,本次實踐的坑位不少, 實操過程儘可能接近最佳實踐(不作hack, 不作騷操做),記錄下來加深理解。nginx

        第一部分: Gitlab CI/CD 原理 和 Gitlab Runner 安裝(這裏使用shell執行器)git

        第二部分: Gitlab CI/CD 實踐:web

  •      宏觀項目架構圖
  •     .gitlab-ci.yml 文件
  •      項目部署目錄

第一部分:gitlab CICD原理

Gitlab CI/CD架構

 

  • Gitlab CI/CD   存儲【構建】和【構建狀態】的api應用程序, 提供友好的管理界面,  構建過程由 .gitlab-ci.yml文件定義,而這個文件通常置於代碼倉庫的根目錄。
  • Gitlab Runner 執行構建過程的應用程序,可與Gitlab Server 造成分佈式部署, 如上圖所示, 其經過api 與Gitlab Server交互

Gitlab CI/CD 配置界面 & Gitlab Runner 安裝

Gitlab CI/CD提供配置界面(項目菜單欄-設置-CI/CD),可指定docker

  - 將要使用何種形式的Runnershell

  -  配置Runner要用到環境變量json

      註冊時須要關注的兩個配置是:api

  •     tags 與此Runner相關的任務標籤, 用於在共享Runner中區分不一樣的Project,.gitlab-ci.yml會用到數組

  •     runner  executor   執行構建任務的方式,這裏使用shell方式服務器

Shell是最簡單的配置執行器,須要將構建所需的全部依賴項手動安裝在安裝了Runner的同一臺計算機上。

      註冊過程和結果請參考下圖:

第二部分:基於docker-compose的Gitlab-CI  實踐

項目架構圖

      

 

原則上不容許自動部署Prod,本次使用Gitlab Runner服務器做爲Gitlab CD的部署機器。

Gitlab-CI Pipeline構建ReceiverAPP、webAPP鏡像(附帶本次git:tag)並推送到hub.docker.com;

Gitlab-CD docker-compose拉取遠端nginx、ReceiveAPP、webapp鏡像,啓動容器。 

  •      Pipeline對每一次提交或合併都會執行build任務, 造成Continous Intergation

  •      Pipeline對git: tag會執行build_Image任務,自動構建至deploy_staging任務,這樣就能造成基於git:tag的部署版本管理(部署出錯,也能很快回滾到上次的部署tag)

本處使用Gitlab Runner 服務器做爲staging部署機器; 原則上不容許自動隨意部署Prod(實踐中登錄到 Prod機器上執行部署命令,如下GitLab-CD也沒有完成Prod的自動部署過程,自行補上登錄終端的腳本便可   

.gitlab-ci.yml 文件

  以上Gitlab Pipeline定義了 build-->build_image-->deploy 三個任務, 某些任務還包括不一樣分支Job,寫.gitlab-ci.yml 的過程就是將以上執行動做腳本化,更多Gitlab-CI的資料

 1 stages:
 2   - build
 3   - build_image
 4   - deploy
 5 
 6 variables:         
 7 # CI_DEBUG_TRACE: "true"                                         
 8   deploy_path: "/home/xxxx/eqidmanager"     # CI變量,用於配置部署目錄 9 
10 before_script:
11   - "docker info"
12 
13 build:
14   stage: build
15   script: 
16     - "for d in $(ls src);do echo $d;prog=$(pwd)/src/$d/$d.csproj; dotnet build $prog; done"
17   tags:                                                 
18     - another-tag
19 
20 build_image:EqidManager:
21   stage: build_image
22   script:
23     - dotnet publish src/EqidManager/EqidManager.csproj  -c release -o ../../container/app/publish/    
24     - docker build --pull  -t $CI_REGISTRY_USER/eqidmanager:$CI_COMMIT_REF_NAME  container/app
25     - docker login -u $CI_REGISTRY_USER  -p $CI_REGISTRY_PASSWORD      
26     - docker push $CI_REGISTRY_USER/eqidmanager:$CI_COMMIT_REF_NAME     
27   tags:    
28     - another-tag
29   only:                #Pipeline Job構建策略,代碼倉庫打tag會執行該任務, 支持正則 30     - tags
31 
32 build_image:EqidReceiver:
33   stage: build_image
34   script:
35     - dotnet publish src/EqidReceiver/EqidReceiver.csproj  -c release -o ../../container/receiver/publish
36     - docker build -t $CI_REGISTRY_USER/eqidreceiver:$CI_COMMIT_REF_NAME container/receiver
37     - docker login -u $CI_REGISTRY_USER  -p $CI_REGISTRY_PASSWORD
38     - docker push $CI_REGISTRY_USER/eqidreceiver:$CI_COMMIT_REF_NAME
39   tags: 
40     - my-tag
41   only:
42     - tags
43 
44 deploy:staging:
45   stage: deploy
46   script:
47     - cd $deploy_path
48     - export TAG=$CI_COMMIT_REF_NAME        # 引入本次CI的git:tag名稱,覆蓋.env文件默認配置 49     - "docker-compose -f docker-compose.yml -f docker-compose.prod.yml build"                        
50     - "docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d" 
51   tags: 
52     - my-tag
53 
54 deploy:prod:
55   stage: deploy
56   script:
57     - # TODO 須要寫腳本登錄到Prod機器上
58     - export TAG=$CI_COMMIT_REF_NAME        
59     - cd $deploy_path
60     - "docker-compose -f docker-compose.yml -f docker-compose.prod.yml build"
61     - "docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d" 
62   tags:
63     - my-tag
64   when: manual

 這裏有些知識點和 坑位須要指出:

第8行: 預先定義的環境變量,該變量定義gitlab CD的部署目錄

第16行:  對src開發目錄下兩個程序執行dotnet build命令

第17行:tags定義具有該tags的Runner能夠執行該任務, 注意這裏的tags必須是字符串數組

第23-26行:構建鏡像並推送到鏡像倉庫的過程,用到兩種CI變量

   - 密鑰變量CI_REGISTRY_USER、CI_REGISTRY_PASSWORD ,可在GitLab-CI 界面配置

     - 預約義變量CI_COMMIT_REF_NAME, 該變量標記構建項目的git:branch或git:tag名稱,用於生成鏡像tag

     注意變量可被重寫,重寫有優先級 http://www.ttlsa.com/auto/gitlab-cicd-variables-zh-docum

第29行; only定義此Job只在產生git:tag時被觸發,與上面咱們使用 CI-COMMIT_REF_NAME 變量相呼應

第47行: Gialab-CI pipeline每一個Job會從新拉取git源碼執行Job任務(可登陸到Gitlab Runner工做目錄下觀察Runner執行過程),CD時須要選擇合適目錄,這是deploy_staging上使用deploy_path CI變量的緣由

第48行:注入本次Gitlab-CI git:tag名稱, 其實是覆蓋了.env同名環境變量

第49行:若存在docker-compose.yml、docker-compose.override.yml 兩個文件,docker-compose命令會自動merge這2個文件(使用docker-compose config命令查看merge 以後的結果)。

第64行:上述Job若沒有出錯,會自動執行下一步;而when指令定義該Job 是須要在界面上手動執行 

部署目錄

 在Gitlab Runner服務器的{deploy_path}路徑下創建了以下部署文件:

├── appsettings.secrets.json
├── docker-compose.prod.yml
├── docker-compose.yml
├── .env
├── EqidManager.db
├── nginx
│   ├── Dockerfile
│   └── nginx.conf
└── receiver.secrets.json
  • 在部署目錄創建定義docker-compose.yml、docker-compose.prod.yml 兩個yml文件,前者定義常規容器服務,後者定義適用於本Prod環境的容器服務
  • 密鑰文件不要進入代碼管理,所以咱們定義appsetting.secrets.json 和 receiver.secrets.json密鑰文件,由dccker-compose.yml掛載進入容器

  • .env文件存儲相對固定、與本次docker-compose命令相關的環境變量,docker-compose命令默認尋找同級目錄下.env文件

------.env 文件----
TAG=master   # 該TAG變量會在Pipeline:deploy_staging任務中被覆蓋,造成基於git:tag的imageName:tag docker_host=172.16.1.1 COMPOSE_PROJECT_NAME=EqidManager DOCKER_REGISTRY=***

 project打上git:tag以後,觸發Gitlab Runner CI/CD Pipeline: 

跳轉到部署目錄->應用本次git:tag->執行docker-compose命令拉取指定tag鏡像並啓動容器。

That'all, 本次應用Gitlab Runner(shell執行器)實踐CI/CD, Gitlab菜單界面有全部構建構成的日誌(便於排查構建問題);另外上文對於關鍵知識均附帶傳送門,可進一步對比研究。

做者: JulianHuang

碼甲拙見,若有問題請下方留言大膽斧正;碼字+Visio製圖,均爲原創,看官請不吝好評+關注,  ~。。~

本文歡迎轉載,請轉載頁面明顯位置註明原做者及原文連接

相關文章
相關標籤/搜索