如何在 Docker 使用 GitLab CI
TLDR
- GitLab 安裝建議:務必設定
external_url以確保 SSH 與 HTTP 連結正確,若使用非標準 Port,需同時設定nginx['listen_port']。 - Volume 掛載:GitLab 的
/var/opt/gitlab建議使用 Docker Volume 而非 Bind Mount,以避免artifacts功能因權限不足而失效。 - Runner 註冊:若 GitLab 網址為
127.0.0.1或localhost,註冊時需手動指定clone_url,否則 Runner 無法連線。 - Docker Executor 權限:若需在 CI 中執行 Docker 指令,需將
/var/run/docker.sock掛載至 Runner,並在config.toml中將privileged設為true。 - 網路模式:Runner 的
network_mode不可設為host,建議使用gitlab_default以確保 Runner 能與 GitLab 容器正常通訊。 - CI 變數限制:Docker Image 名稱僅支援小寫,若專案名稱含大寫,請使用
$CI_PROJECT_PATH_SLUG變數。
在 Docker 上安裝 GitLab
在 Docker 環境中部署 GitLab 時,設定檔的正確性至關重要。
關鍵設定與注意事項
- 什麼情況下會遇到問題:若未正確設定
external_url,GitLab 產生的 SSH 與 HTTP 儲存庫連結將會失效或顯示為亂碼。 - 解決方案:
- 在
docker-compose.yml的GITLAB_OMNIBUS_CONFIG中明確指定external_url。 - 若使用非 80 Port,必須同步設定
nginx['listen_port']。 - 避免使用 Bind Mount 掛載
/var/opt/gitlab,改用 Docker Volume 以解決artifacts功能的權限問題。 - 若出現「invalid port specification」錯誤,請將 Port 對應(如
5022:22)加上引號。
- 在
yaml
# docker-compose.yml 範例片段
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://127.0.0.1:5080/'
nginx['listen_port'] = 80
gitlab_rails['gitlab_shell_ssh_port'] = 5022
ports:
- "5080:80"
- "5022:22"在 Docker 上安裝與註冊 GitLab Runner
Runner 的設定決定了 CI/CD 任務能否順利執行。
註冊與配置重點
- 什麼情況下會遇到問題:當 GitLab 容器使用
127.0.0.1或localhost作為網址時,Runner 註冊後會因為無法解析位址而無法拉取程式碼。 - 解決方案:
- 註冊後編輯
config.toml,手動加入clone_url指向 GitLab 容器的正確 IP。 - 若要執行 Docker 指令(如
docker build),必須掛載docker.sock。
- 註冊後編輯
toml
# config.toml 設定範例
[[runners]]
url = "http://172.20.0.2"
clone_url = "http://172.20.0.2"
executor = "docker"
[runners.docker]
privileged = true
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
network_mode = "gitlab_default"WARNING
network_mode 切勿設定為 host,否則可能導致 GitLab 服務回應異常。
GitLab CI 實例:.NET 6 專案
透過 .gitlab-ci.yml 定義 Build、List、Deploy 三個階段,實現自動化流程。
核心實作細節
- 什麼情況下會遇到問題:在
list-job中輸出檔案路徑時,若檔案名稱包含中文,會因編碼問題被轉譯。 - 解決方案:使用
git config --global core.quotepath false關閉特殊字元轉譯。 - 部署注意事項:由於 Docker Image 名稱僅支援小寫,請使用
$CI_PROJECT_PATH_SLUG變數來動態產生 Image 名稱。
yaml
# .gitlab-ci.yml 範例片段
deploy-job:
stage: deploy
script:
- cd build
- docker build --tag $CI_PROJECT_PATH_SLUG:latest .
- docker stop $CI_PROJECT_NAME || true && docker rm $CI_PROJECT_NAME || true
- docker run -d -p 9080:80 --name $CI_PROJECT_NAME $CI_PROJECT_PATH_SLUG:latest總結
透過將 Runner 的 privileged 權限開啟並掛載 docker.sock,可以讓 Runner 直接呼叫宿主機的 Docker Engine 進行容器化部署,這是最適合在單機 Docker 環境下進行 CI/CD 的做法。
異動歷程
- 初版文件建立。