Simple gitlab CI/CD with docker
年初挑了bitbucket + jenkins作為docker內部簡易自動化建置與部署的設置
那時候由於jenkins是內網的服務,bitbucket沒辦法送webhook進來,無法實作pipeline
自建bitbucket也是可以,但有沒有一個服務是一條龍做完的呢?就是gitlab
由於gitlab community edition (簡稱gitlab-ce) 跟 gitlab-runner免費授權的緣故
成為現在許多企業內部專案管理與自動化建置、測試與部署的首選
以下會以gitlab-ce + gitlab-runner兩個docker image為基底,建置兩個容器服務
並拿Angular、免費網域靜態檔案放置服務Surge當實作目標,走過一遍gitlab CI/CD
那時候由於jenkins是內網的服務,bitbucket沒辦法送webhook進來,無法實作pipeline
自建bitbucket也是可以,但有沒有一個服務是一條龍做完的呢?就是gitlab
由於gitlab community edition (簡稱gitlab-ce) 跟 gitlab-runner免費授權的緣故
成為現在許多企業內部專案管理與自動化建置、測試與部署的首選
以下會以gitlab-ce + gitlab-runner兩個docker image為基底,建置兩個容器服務
並拿Angular、免費網域靜態檔案放置服務Surge當實作目標,走過一遍gitlab CI/CD
整個架構圖如下:
gitlab-ce 為整個專案程式碼管理服務與pipeline主控台
gitlab-runner 則是當pipeline啟動時,會根據gitlab特有的
gitlab-ce 每個專案會有一組自己的token,用以註冊gitlab-runner
gitlab-runner註冊時,可以選擇執行方式(executor),我們選用docker
gitlab-runner會另外開幾個container來pull code與執行CI/CD,最後push到surge上
gitlab-runner 則是當pipeline啟動時,會根據gitlab特有的
gitlab-ci.yml
執行CI/CDgitlab-ce 每個專案會有一組自己的token,用以註冊gitlab-runner
gitlab-runner註冊時,可以選擇執行方式(executor),我們選用docker
gitlab-runner會另外開幾個container來pull code與執行CI/CD,最後push到surge上
前置作業:
(1). 註冊好surge的帳戶與自定義的網域名稱
(2). 確認docker的記憶體要4gb ram以上 (開發環境為Docker for Mac)
(3).
(4).
(5). gitlab-ce版本:10.6.1
(1). 註冊好surge的帳戶與自定義的網域名稱
(2). 確認docker的記憶體要4gb ram以上 (開發環境為Docker for Mac)
(3).
gitlabDocker
目錄,主要放置 docker-compose.yml(4).
testCICD
目錄,主要放置 Angular與gitlab-ci.yml(5). gitlab-ce版本:10.6.1
主要步驟有四:
- 撰寫docker-compose file,確認兩個服務之間可以正常連線
- 設定User、Group、Project,模擬一般專案合作使用狀況
- 設定 gitlab-ce pipeline,註冊runner
- Push Code & auto-run pipeline
除了2.以外,會分享一些自己踩到的雷點,希望大家少踩一點~
- 撰寫docker-compose file,確認兩個服務之間可以正常連線docker-compose.yml
version: "3.3" services: gitlab-ce: image: gitlab/gitlab-ce:latest container_name: 'gitlab-ce-demo' ports: - '22:22' - '80:80' - '443:443' volumes: - gitlab-etc-volume:/etc/gitlab - gitlab-varlog-volume:/var/log/gitlab - gitlab-varopt-volume:/var/opt/gitlab hostname: 'gitlab-ce-demo' networks: gitlab-demo-network: aliases: - gitlab-ce gitlab-runner: image: gitlab/gitlab-runner:latest container_name: 'gitlab-runner-demo' volumes: - /Users/Shared/gitlab-runner/config:/etc/gitlab-runner - /var/run/docker.sock:/var/run/docker.sock networks: gitlab-demo-network: networks: gitlab-demo-network: volumes: gitlab-etc-volume: gitlab-varlog-volume: gitlab-varopt-volume:
- yaml 解譯檔案時,會因為本身60進位制的設定而對低於60的數字判讀時會有錯誤
所以ports如果要開59以下的,用quotes(``
)包起來才不會有問題 - 若要保存gitlab-ce的檔案,建議另外命名一個volume
掛載外部位置可能會因權限問題而無法正常執行gitlab-ce
因為gitlab-ce其實在裡頭用不同使用者身份安裝了不少服務,包成一個docker容器
掛載時可以選擇身份,但由於他本身權限的設定,沒辦法一個身份滿足所有容器內服務
如果只是備份資料,其實只要命名一個空間,接著再透過備份還原的指令即可保存volumes - hostname設定
由於gitlab-ce的url 會基於hostname生成,若不指名則會隨機產生一個名稱
gitlab-runner會基於gitlab-ce給他的hostname連過去
而不是註冊gitlab-runner時設定的domain name。
因此,我們必須指名hostname然而容器之間的連結是靠container_name與alias設定
若要指名hostname則另外要對應IP,但是在docker裡容器預設是浮動ip
因此這裡有個小trick:
將hostname跟container_name設定一致,就不用hardcode ip跟hostname下docker-compose up
,等一陣子之後到localhost會看到以下畫面,就表示成功了!
這個密碼是root帳號的密碼
因為還沒註冊,terminal會看到gitlab-runner有以下錯誤是正常的:gitlab-runner-demo | ERROR: Failed to load config stat /etc/gitlab-runner/config.toml: no such file or directory builds=0
- 設定User、Group、Project,模擬一般專案合作使用狀況
(以下步驟不一一截圖)接著我們,註冊一個lyt與kobayashi的user
kobayashi是group(teamA)跟project(testCICD)的擁有者
並將lyt加入teamA群組,lyt的權限為reporter,
再將lyt加入testCICD專案,lyt的權限為developer
結果如下:
左邊是該project(也稱repository)權限為developer,他可以上unprotected branch的code
右邊是該project的owner,擁有最高權限。比developer多了設定專案的各種參數以外
亦處理對protected branch的pull request,驗過沒問題就merge
*關於權限的細部說明可以參考gitlab Q&A為了demo CICD方便,省去pull request操作,我們統一用owner kobayashi操作
也別忘了放上自己的ssh public key (e.g.,id_rsa.pub) - 設定 gitlab-ce pipeline,註冊runner
由於是跑localhost的docker-compose,加上runner也是用docker去跑
所以在這有幾個注意事項,依編號說明- 網域名稱填寫
http://gitlab-ce-demo
,為runner輪詢的目標之一 - 該專案的Token在 CI/CD settings裡,貼上即可
- 設定與
gitlab-ci.yml
裡,對應的tag名稱,這裡寫dev,註冊成功後可在gitlab-ce修改 - 如果你希望該pipeline的任何一筆change上了就要跑CI/CD,而不管tag,這裡可以填 true
- 我們是用docker,會產生新容器
為了讓他加入gitlab-ce docker networks裡,在下一步做修改 - 打開編輯器後,加上network_mode與links兩行,結果如下
concurrent = 1 check_interval = 0 [[runners]] name = "Demo CI/CD" url = "http://gitlab-ce-demo" token = "615f710e4728953ee518102d10fe28" executor = "docker" [runners.docker] tls_verify = false image = "trion/ng-cli-karma" privileged = false disable_cache = false volumes = ["/cache"] shm_size = 0 network_mode = "gitlabdocker_gitlab-demo-network" links = ["gitlab-ce-demo"] [runners.cache]
- 網域名稱填寫
- Push Code & auto-run pipeline
- 初始化專案,並pull下來
- 在testCICD資料夾裡,新增angular專案
npm install surge --save-dev
如果是第一次註冊沒有帳號、token跟網域需打以下指令:
./node_modules/.bin/surge
註冊完會拿到註冊信箱跟token,記起來- 在gitlab-ce上設定surge所需參數如下 (Secret variables)
把登入信箱與token放在value裡即可 - 撰寫
gitlab-ci.yml
這是整個CI/CD的重頭戲,push上去就會自動觸發了image: trion/ng-cli-karma cache: paths: - node_modules/ deploy_stage: stage: deploy environment: Stage tags: - dev only: - master script: - rm ./package-lock.json - npm install - ./node_modules/@angular/cli/bin/ng test --progress false --single-run=true --watch=false - ./node_modules/@angular/cli/bin/ng e2e --progress false --watch=false - ./node_modules/@angular/cli/bin/ng build --progress false --prod --base-href demo-ci-stage.surge.sh - ./node_modules/.bin/surge -p dist/ --domain demo-ci-stage.surge.sh
- only 要執行pipeline的branch
- tags這裡設定的就是要與runner相互對照的
若沒有對應到runner的tag,也沒有無視tag的runner待命的話會pending住 - script就是每一行建置、測試、部署的指令
surge拿到的domain設置在末兩行 (e.g.,demo-ci-stage.surge.sh
)
最後一行就是將檔案放到該網域上
- git commit & push後,看gitlab-ce pipeline
看到pipeline #3即是按照上述步驟剛push上去的狀態第一次cancel是因為 gitlab-ci.yml沒有宣告對應的tag而pending,最後取消
第二次fail是因為沒有安裝surge - 接著可以看看在build的過程
從gitlab-ce-demo pull master branch後
會按照script,一行一行執行
每次build的過程都會被記錄起來,也可以重新build - Build成功後,可以看到
http://demo-ci-stage.surge.sh/
結果如下
- 為落實CICD的精神,修改後立刻push,修改如下
- 看看pipeline與部署結果
以上就是整個gitlab-ci + gitlab-runner的實作流程
希望這篇教學可以讓需要的人少踩一些雷<(_ _)>
References:
留言
張貼留言