CI/CD 十關

LV.8/10

Services

用 services 在 job 旁邊開 Redis 與 PostgreSQL,跑真正連得到資料庫的整合測試

進階約 25 分鐘services、alias、整合測試、entrypoint

學習目標

  • 用 services 在 job 旁邊開暫時的 Redis、PostgreSQL。
  • 用 alias 當主機名稱連線。
  • 知道 job 變數會傳給 service,以及怎麼等 service 準備好。
  • 會用 image:entrypoint 覆寫映像的進入點。

觀念

┌──────── 同一個 job 的網路 ────────┐
│  job 容器 (postgres:17-alpine)    │
│     psql -h db ───────────────┐   │
│  service 容器 (alias: db) ◀───┘   │
└───────────────────────────────────┘
job 結束 → 兩個容器都刪掉,資料不會留下來
設定說明
services[].name服務的映像,請固定版本
services[].alias在 job 裡用來連線的主機名稱
variablesjob 與 service 都拿得到,postgres 用 POSTGRES_DB 等變數初始化
image:entrypoint: [""]不跑映像預設的進入點,避免它搶先啟動資料庫

等服務準備好

service 啟動需要幾秒,直接連可能失敗。本關用迴圈等:

sh
for i in $(seq 1 30); do pg_isready -h db -U tutorial && break; sleep 1; done

安全提醒

本關的 PostgreSQL 用 POSTGRES_HOST_AUTH_METHOD: trust 免密碼,只因為它是 job 結束就刪掉的測試資料庫,而且只在 job 自己的網路裡。正式環境一律要密碼,密碼放 CI/CD 變數並勾選 Masked。

動手做

  1. 看 postgres-test 的紀錄,最後會印出 10 筆課程。
  2. 把 schema.sql 多加一筆,grep -qx 10 會失敗:測試真的有讀資料庫。
  3. 把 alias: db 改成 alias: database,連線會失敗,記得 script 一起改。

常見錯誤

  • 用 localhost 連 service:service 是另一個容器,要用 alias。
  • service 用了 latest:哪天大版本升級,測試突然失敗。
  • 以為 service 的資料會保留到下一個 job:不會,要保存請用 artifacts。

下一關

Lv.9 把部署變成看得見的環境:environments。

範例檔案

資料夾 lv08-services/ 的全部檔案。.gitlab-ci.yml 可以直接複製到自己的專案根目錄執行。

lv08-services/.gitlab-ci.yml
lv08-services/.gitlab-ci.yml
# Lv.8 Services:在 job 旁邊開一個暫時的資料庫或服務,做整合測試
# service 是另一個容器,和 job 在同一個網路,用 alias 當主機名稱連線;job 結束就刪掉。

stages:
  - integration

redis-test:
  stage: integration
  image:
    name: redis:7.4-alpine
    entrypoint: [""]            # 不用映像預設的進入點,直接跑我們的 script
  services:
    - name: redis:7.4-alpine
      alias: cache
  script:
    - redis-cli -h cache ping
    - redis-cli -h cache set lesson lv08
    - test "$(redis-cli -h cache get lesson)" = "lv08"
    - echo "Redis 讀寫正常"

postgres-test:
  stage: integration
  image:
    name: postgres:17-alpine
    entrypoint: [""]
  services:
    - name: postgres:17-alpine
      alias: db
  # job 的變數也會傳給 service,postgres 映像用這些變數初始化資料庫
  variables:
    POSTGRES_DB: tutorial
    POSTGRES_USER: tutorial
    # 只有這個一次性的測試資料庫用免密碼登入;正式環境一律要密碼,密碼放 CI/CD 變數
    POSTGRES_HOST_AUTH_METHOD: trust
  script:
    - for i in $(seq 1 30); do pg_isready -h db -U tutorial && break; sleep 1; done
    - psql -h db -U tutorial -d tutorial -v ON_ERROR_STOP=1 -f lv08-services/schema.sql
    - psql -h db -U tutorial -d tutorial -tAc "SELECT count(*) FROM lessons" | grep -qx 10
    - psql -h db -U tutorial -d tutorial -c "SELECT id, title FROM lessons ORDER BY id"
lv08-services/schema.sql
lv08-services/schema.sql
-- Lv.8 整合測試用的資料表:十關課程
CREATE TABLE lessons (
  id    integer PRIMARY KEY,
  title text    NOT NULL
);

INSERT INTO lessons (id, title) VALUES
  (1, '第一條 Pipeline'),
  (2, 'Stages 與 Jobs'),
  (3, 'Artifacts'),
  (4, 'Variables'),
  (5, 'Cache'),
  (6, 'Rules 與 workflow'),
  (7, 'Needs 與 DAG'),
  (8, 'Services'),
  (9, 'Environments'),
  (10, '實機部署到 k8s');