上回說到 CI/CD 的第一步會是 Build ,今天就來實際了解如何建置 Build Stage。
要如何使用專案裡的 Dockerfile
自動建置 Image,需要先了解 GitLab CI 裡的 Job 是如何運行的,在.gitlab-ci.yml
中定義 Job 的格式如下
job-name:
stage: stage-name
script:
- echo "script"
對流水線中每一個 Job ,GitLab Runner 會透過 Docker 啟動 Container 做為此 Job 的環境,而容器要使用什麼 Image 可以在 .gitlab-ci.yml
上定義,會根據要下達的指令定義所需 Image 。
像是
Script
中若有 python xxx.py 的指令,可以選擇使用 python 的 Image 做為 Job 的容器。
而現在的目標是希望在 Job 中能夠建置 Image ,也就是說,會需要在 script
裡會下達如 docker build
的指令,所以要使用的 Image 就會是 Docker 本身,在 Docker 裡建置 Docker 容器,這種作法稱為 Docker-in-Docker
,在.gitlab-ci.yml
可以這樣配置
image: docker
services:
- docker:dind
在 GitLab 文檔中的 Use Docker to build Docker images 有
Docker-in-Docker
方法的詳細介紹。
這樣就可以 Build Docker Image 了,但緊接著會遇到下一個問題,每一次 Job 運行完成後 GitLab Runner 會將容器刪除,所以 Build 好的 Image 需要先 Push 到可以保存的地方,而 GitLab 很好心的提供了 GitLab Container Registry ,讓我們可以儲存在 CI/CD 運行時建置出的 Image。
準備工作差不多完成,可以開始撰寫 .gitlab-ci.yml
了,一開始會將重複使用的值定義為 variabes,如 CI_IMAGE
就是保存在 GitLab Registry 的 Image 名稱。為了區別每次流水線建置出的 Image , Tag 會打上本次 Commit 產生的 SHA 來保證名稱唯一性,在 Predefined variables reference 有參數可以直接代入。
variables:
IMAGE_NAME: node-project
CI_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
$CI_REGISTRY_IMAGE
為此專案 GitLab Container Registry 的位置,而$CI_COMMIT_SHORT_SHA
是 SHA 的前八碼。
接著在 Build Job 中,透過 docker build
以及 docker push
建置 Image 並上傳到 Registry ,因為需要有上傳權限,所以會先使用 docker login
登入取得 Push 權限。
build:
stage: build
only:
- dev
- master
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $CI_IMAGE .
- docker push $CI_IMAGE
有了 Image 後,接下來的 Job 就能使用 docker pull
將 Image 下載下來進行其他操作,像是在 Test Job 就可以使用 docker run <image> <command>
運行測試腳本。
test:
stage: test
only:
- dev
- master
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $CI_IMAGE
- docker run $CI_IMAGE echo "run test script here"
基本概念大致介紹完成,就來實際建立 Build Stage 吧!
進入 Cloud Shell 網站
點擊左上 Explorer -> Open Folder -> 選擇 project 資料夾 -> Open
.gitlab-ci.yml
檔案並用以下內容取代image: docker
services:
- docker:dind
variables:
IMAGE_NAME: node-project
CI_IMAGE: $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
stages:
- build
- test
- publish
- stg-deploy
- prod-deploy
build:
stage: build
only:
- dev
- master
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $CI_IMAGE .
- docker push $CI_IMAGE
test:
stage: test
only:
- dev
- master
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $CI_IMAGE
- docker run $CI_IMAGE echo "run test script here"
publish:
stage: publish
only:
- master
script:
- echo "publish job"
stg-deploy:
stage: stg-deploy
only:
- master
script:
- echo "Staging deploy job"
prod-deploy:
stage: prod-deploy
only:
- master
script:
- echo "Production deploy job"
when: manual
cd ~/project
git add .
git commit -m "add build and test stages"
git push origin master
Enter
Username for 'https://gitlab.com':
Password for 'https://user@gitlab.com':
到 GitLab 網站,點擊之前建立的 web app 的 Repository
進入到 Repository 後,點擊 CI/CD -> Pipelines
會看到新的 CI/CD Pipeline ,等待一段時間直到運行成功。
Packages & Registries -> Container Registry
可以發現有 webapp 專案的 Image。
點擊進去就能查看 Tag 名稱。
這裡的 Tag 名稱會跟本次 Commit 的前八碼 SHA 吻合。
今天完成了 Build Stage , 也簡單說明 Test Stage 的方式,明天會學習如何將 Image 上傳至 Google Container Registry 。