Logo image
GitHub LinkedIn

【Gitlab】環境建置及 CI 初嘗試

Relume placeholder avatar
張三

2022年1月11日

5分鐘閱讀

Relume placeholder image

前言

平常的時候有耳聞,前端工程師雖然把網站建好了,但是要把 React 專案部署到客戶指定的 Server 上通過驗收,也是一個大問題。加上最近因為待的團隊偏小,也在環境建置上遇到很多奇怪的問題:

為什麼我改了環境變數,但是 Docker 還是沒有部署到 3306 port 上? 我已經想好怎麼寫程式碼,但是我要怎麼架一個服務,讓同事或是客戶可以看到我的成果?

如果把視野拉大,在建置 React 專案之外,Work Flow 也有許多需要人工處理的事情:

圖片來源:https://docs.gitlab.com/ee/ci/

  • Plan:規劃專案的需求
  • Code:撰寫程式碼
  • Test: 測試程式碼 — 日常工作在這
  • Review:Code Review
  • Deploy:部署程式碼到客戶指定的 Server

因此最近趁著專案的空檔,透過一些小服務來熟悉環境建置的流程。這篇週間札記就來分享一下我在環境建置及 CI 上的初嘗試。

這篇會介紹到:

  • Docker
  • Gitlab Runner & Ubuntu Setup

目錄

什麼是 CI/CD

CI/CD 是持續整合(Continuous Integration)和持續部署(Continuous Deployment)的縮寫,是一種軟體開發實踐,藉由自動化的流程來測試、打包、部署程式碼。

  • CI:持續整合,是指開發者將程式碼整合到共享儲存庫中,然後自動化的進行測試,確保程式碼的品質。

  • CD:持續部署,是指將程式碼部署到生產環境中,並且自動化的進行部署。

1、Docker 與環境建置

在真的跳到如何建置 Docker 之前,先聊一下之前從頭開始架設 Server 的產痛經驗。透過 Digital Ocean 起一個虛擬機,並建立一個服務大概需要經歷這個流程:

但是透過 Docker,只要租借好一台虛擬機,只要執行

docker pull // Docker Hub 下載已經建立好的 Image
docker run -p 3000:3000 // 建立 Container, 並且將Docker內部的 3000 port對應到本機的 3000 port

就可以建立一個服務,這樣就可以省去很多時間在環境建置上。

1-1 VM vs Docker

在很早之前,分配服務是以記憶體的方式來分配的,例如記憶體的某一個區塊切出一個虛擬機器,然後在這個虛擬機器上安裝作業系統、建立防火牆,在作業系統上安裝應用程式。但是以 APP 的角度出發,我們可能需要根據不同專案有不同的 node 版本環境,這樣的話,就會有很多不同的 VM 來管理。

nvm use 14 // 專案 A 需要 node 14

而 Docker 讓環境建置更加輕巧,透過 Dockerfile 來建立 Image,然後透過 Image 來建立 Container,這樣就可以達到『一次建立,到處運行』的效果。

註:Image 就像是一個藍圖,Container 是根據藍圖建立的實體,也就是實際執行的環境。

FROM node:14 // 使用 node 14 的 Image

WORKDIR /app // 設定工作目錄在 /app

COPY package.json . // 複製 package.json 到 /app

RUN npm install // 安裝 package.json 的套件

COPY . . // 複製所有檔案到 /app

CMD ["npm", "start"] // 執行 npm start

接著就可以透過 terminal 來建立 Image,然後建立 Container。

docker build -t my-node-app . // 建立 Image
docker run -p 3000:3000 my-node-app // 建立 Container, 並且將Docker內部的 3000 port對應到本機的 3000 port

1-2 Dockerfile & Docker Compose

如果有多個服務需要建立,這時候就可以透過 Docker Compose 來管理多個 Container。我們需要在每一個專案資料夾定義好 Dockerfile,然後在根目錄透過 docker-compose.yml 來管理。

version: '3'
services:
   frontend:
      build: ./frontend
      image: Dockerfile
     ports:
       - "3000:3000"
   backend:
       build: ./backend
       image: Dockerfile
       ports:
          - "3001:3001"
   mongo:
      image: mongo
      ports:
         - "27017:27017"

這樣就可以透過 docker-compose 來一次啟動所有服務。

docker-compose build // 建立所有 Image
docker-compose up // 啟動所有 Container

Gitlab Runner & Ubuntu Setup

在本地打包好專案後,就是我們心心念念的怎麼簡單在 Server 上面跑 docker-compose up 起服務,這邊以 Gitlab 的自動化流程為例。

2-1 Gitlab Runner

在接觸 Gitlab Runner 之前,其實自己也很好奇,CI / CD 倒底是誰在觸發。簡單來說我們就是委託一個像是 Gitlab Runner / Github Action 這樣持續在監控的代理人,在被授予權限後,替我們在 VM 上執行 CI / CD 流程。

根據官方的文件,Gitlab Runner 可以在幾個不同的環境中執行,例如:

  • Giltab 幫你管理的 Runner(GitLab-hosted)
  • 自己的 Server(Self Management)

詳情可以參考:GitLab Runner

今天挑選的是自己的 Server 出來講。

2-2 Ubuntu Setup

2-2-1 安裝所需的套件

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin // 安裝 Docker,詳情參考官方說明
sudo apt-get install gitlab-runner // 安裝 Gitlab Runner

然後需要給予 Gitlab Runner 執行 Docker 的權限。

sudo usermod -aG docker gitlab-runner

2-2-2 設定 Gitlab Runner

Ubuntu 環境

  1. 需要確保 Gitlab Runner 有組織的憑證,例如 my-org.crt,並更新憑證

詳情參考 Self-signed certificates or custom Certification Authorities

sudo cp my-org.crt /usr/local/share/ca-certificates/my-org.crt // 複製憑證到目標資料夾
sudo update-ca-certificates
  1. 給予 Gitlab Runner 目標資料夾的管理權限
sudo chown -R gitlab-runner:gitlab-runner /opt/my-project
sudo chmod -R 755 /opt/my-project
權限類型數字表示符號表示說明
讀取4r允許讀取檔案內容或列出目錄內容。
寫入2w允許修改檔案內容、在目錄中新增或刪除檔案。
執行1x允許執行檔案 (如果是程式) 或進入目錄 (如果是目錄)。
無權限0-不允許任何操作。

755 代表的涵意:

  • 擁有者:7 (4+2+1) = 讀取、寫入和執行
  • 群組:5 (4+1) = 讀取和執行
  • 其他人:5 (4+1) = 讀取和執行
  1. 設定 Gitlab Runner
  • 在 Gitlab 的專案中,找到 Settings -> CI/CD -> Runners -> Set up a specific Runner manually,並建立一個 Runner。

  • 在 Server 上執行 gitlab-runner register,並填入相關資訊

sudo gitlab-runner register
  • 設定 token
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/): // 輸入 Gitlab 的 URL
Please enter the gitlab-ci token for this runner: // 輸入 Gitlab token
Please enter the gitlab-ci description for this runner: // 輸入 Runner 的描述

到這邊 Server 就有一個代理人可以執行 CI/CD 了。

2-2-3 設定 .gitlab-ci.yml

在專案根目錄建立 .gitlab-ci.yml,並設定好 CI/CD 流程。

stages:
  - build
  - deploy

build:
  stage: build
  tags:
    - my-runner // Runner 的名稱
  before_script:
    #如果需要身份驗證,或是其他程序,可以在這邊設定
    #也可以在這邊設定環境變數

    #複製 git
    - |
      if [! -d /opt/my-project]; then
        git clone https://gitlab.com/my-project.git /opt/my-project
      else
        if [ -d /opt/my-project/.git ]; then
        cd /opt/my-project & git pull
        else
        echo "Directory is not a git repository"
        fi
      fi

  script:
    - cd /opt/my-project // 切換到專案目錄
    - docker-compose build
  only:
    - master

deploy:
  stage: deploy
  script:
    - docker-compose up -d // 啟動服務
  only:
    - master

這樣就可以透過 Gitlab Runner 來自動化部署服務了。

git add .
git commit -m "Add .gitlab-ci.yml"

可以透過 git push 來觸發 CI/CD 流程。

結語

你可以幫我開一個 VM 嗎?我大概下午程式碼寫好就能推到測試站。

經過一個禮拜的努力,終於能脫離神手黨,有底氣可以講出這句話了。在這個過程中,稍微脫離的程式碼,也體驗到了『建立服務』是什麼感覺。

探索更多精彩內容

繼續閱讀,了解更多技術與個人經歷的精彩文章。