gitlab-runner 的 executors 之 docker
- GitLab Runner 實現了許多執行程序,可用於在不同的場景中運行構建。所有執行程序分別為:
- SSH
- Shell
- Parallels
- VirtualBox
- Docker
- Docker Machine (auto-scaling)
- Kubernetes
- Custom
- 本文主要介紹 docker 執行程序:
- 兩種不同的使用方式
- 踩過的坑
- 一些例子與經驗
- 這是一個很好地選擇。因為它可以提供一個干凈的構建環境,項目所有依賴項都可以放到 docker 鏡像中。同時,它還可以輕松創建具有依賴服務的構建環境,比如 MySQL。參考 https://docs.gitlab.com/runner/executors/README.html
- GitLab CI/CD 工作原理: https://docs.gitlab.com/ee/ci/introduction/index.html#how-gitlab-cicd-works
- 在 GitLab CI/CD 中構建 Docker 鏡像:https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
兩種使用方式
docker-in-docker
- 文檔:https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-executor
- 這種方式是使用需要運行在特權模式
privileged
下的特殊的 Docker 鏡像——docker-in-docker(dind)和所安裝的 docker 工具來執行腳本 - GitLab Runner 注冊選擇 docker 和
privileged
模式
sudo gitlab-runner register -n \
--url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
--docker-image "docker:stable" \
--docker-privileged
-
以上命令將注冊一個使用
docker:stable
鏡像的 Runner,它使用privileged
模式啟動構建和服務容器。這也是使用docker-in-docker模式必須使用的設置 -
注意:通過
--docker-privileged
啟用特權模式,禁用容器的所有安全機制,並將主機暴露在權限提升中,這可能導致容器中斷。更多信息查看 Docker 官方文檔運行時特權和 linux 功能 -
上面的命令得到對應配置文件如下
[[runners]]
url = "https://gitlab.com/"
token = TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:stable"
privileged = true
disable_cache = false
volumes = ["/cache"]
[runners.cache]
Insecure = false
.gitlab-ci.yml
例子如下,參考https://gitlab.com/gitlab-examples/docker
image: docker:latest
services:
- docker:dind
build:
stage: build
script:
- docker build -t test .
- 缺點和不足如下:
- 使用 docker-in-docker 時,每個作業都處於干凈的環境中,沒有過去的歷史記錄。並發任務執行正常,因為每個構建都有自己的 Docker 引擎實例,因此它們不會相互沖突。但這也意味着工作可能會變慢,因為沒有層緩存
- 默認情況下,docker:dind 使用的--storage-driver vfs 是最慢的形式。要使用其他驅動程序,請參閱 使用 overlayfs 驅動程序
- 由於 docker:dind 容器和運行器容器不共享其根文件系統,因此任務的工作目錄可用作子容器的安裝點。例如,如果您要與子容器共享文件,則可以在/builds/$CI_PROJECT_PATH 其下創建子目錄並將其用作掛載點(有關更詳細的說明,請查看問題#41227)
使用 Docker 套接字綁定
- 另一種方法是綁定
/var/run/docker.sock
到容器中,以便 Docker 在該映像的上下文中可用 -
注意:如果在使用 GitLab Runner 11.11 或更高版本時綁定 Docker 套接字,則無法再將其 docker:dind 用作服務,因為也會對服務進行卷綁定,從而使這些服務不兼容
- Runner 注冊命令如下
sudo gitlab-runner register -n \
--url https://gitlab.com/ \
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
--docker-image "docker:stable" \
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
- 以上命令將注冊一個使用
docker:stable
鏡像的 Runner。注意:他是用的是 Runner 本身的 Docekr 守護程序,而 docker 命令生成的任何容器都是 Runner 的兄弟,而不是 Runner 的子節點。 - 上面的命令得到對應配置文件如下
[[runners]]
url = "https://gitlab.com/"
token = REGISTRATION_TOKEN
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:stable"
privileged = false
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
[runners.cache]
Insecure = false
- 對應的
.gitlab-ci.yml
例子如下
image: docker:stable
before_script:
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
- 可以看到,這個模式不需要使用服務,直接通過套接字通信。此模式也是有一些需要注意的地方:
- 由於是共享 docker 守護程序,項目的操作會真實產生影響。比如項目如果運行
docker rm -f $(docker ps -a -q)
,那么將會刪除所有容器 - 並發可能會有沖突,比如創建相同的名稱的容器
- 由於創建的容器是 Runnner 的兄弟,所以文件與目錄的共享是在主機上下文完成,而不是構建容器上下文
- 由於是共享 docker 守護程序,項目的操作會真實產生影響。比如項目如果運行
總結
- 選擇兩種方式都各有好壞,可根據實際情況進行選擇。這里還是推薦用第二種,因為第一種真的很干凈,所以很慢
- 做好權限管理和控制,避免危險的腳本
- 還有一點是,指定鏡像版本的時候,最好指定具體的版本。比如使用第一種模式,引入服務
docker:dind
,最好使用docker:18.09.8-dind
。避免鏡像拉取策略,每次拉取最新的鏡像,導致實際是docker:19.0-dind
,與安裝的 docker 版本不符,發生一些意想不到的錯誤