【DevOps工具篇】Gitlab Runner设置(使用Docker in docker作为Runner)
@TOC
推荐超级课程:
强烈建议学习本文之前,先阅读学习此篇:
在这篇文章中,我们将使用另一种称为“Docker in Docker”的方法,在GitLab运行程序服务中注册docker执行器,以便构建、测试和部署我们的容器化项目。
Docker in Docker
Docker in Docker简而言之,就是你在docker容器内运行一个docker引擎(守护进程),而不是在宿主机上运行docker引擎。如果你想要在一个专用的docker引擎中管理容器,与宿主机的docker引擎隔离,并且担心访问宿主机的docker引擎可能会出现问题,那么Docker in Docker可能会很有用。
更新Docker Compose文件
在我们开始注册docker-in-docker执行器之前,我们需要对我们的docker-compose.yml
文件进行一些小的更新。
version: '3.8'
services:
gitlab-server:
image: 'gitlab/gitlab-ce:latest'
container_name: gitlab-server
environment:
GITLAB_ROOT_EMAIL: "admin@example.com"
GITLAB_ROOT_PASSWORD: "Abcd@0123456789"
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://localhost:8000'
nginx['listen_port'] = 8000
ports:
- '8000:8000'
volumes:
- ./gitlab/config:/etc/gitlab
- ./gitlab/data:/var/opt/gitlab
# 添加gitlab服务器到自定义网络的更改
networks:
- gitlab-in-docker
gitlab-runner:
image: gitlab/gitlab-runner:alpine
container_name: gitlab-runner
network_mode: 'host'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
添加自定义docker网络的更改
networks:
gitlab-in-docker:
name: gitlab-in-docker
driver: bridge
我们在这里所做的更新是将GitLab服务器容器放在一个名为gitlab-in-docker
的自定义docker网络中,驱动程序为bridge
。我们这样做的原因是,使用docker in docker的docker执行器无法与docker host
网络一起工作,因为docker in docker使用容器链接,而宿主网络不能与容器链接一起使用。
至少当我在尝试使用dind服务时,这是发生的情况
因此,为了在我们的流水线作业中克隆项目仓库,作业的容器将使用其容器名称访问我们的GitLab服务器,即http://gitlab-server:8000
。由于我们没有使用host
网络,所以无法从作业的容器内通过[http://localhost:8000](http://localhost:8000/)
访问GitLab服务器。
因此,我们需要将GitLab服务器容器和作业执行器容器都放在一个名为gitlab-in-docker
的自定义网络中,这样它们就可以通过容器名称而不是localhost相互访问。
在注册运行器执行器时,运行器需要访问服务器容器。它将通过localhost获得访问权限,因为服务器可以通过http://localhost:8000
访问,并且运行器容器在host
网络上,所以它可以访问localhost
。
作业在克隆仓库时需要访问服务器。它将通过使用服务器容器名称gitlab-server
来访问,因为作业容器和服务器容器都在同一个网络中,即gitlab-in-docker
网络。
对网络感到厌倦了?让我们跳转到运行器注册部分
注册Docker in Docker执行器
转到仓库 → 设置 → CI/CD → 运行器
点击新建项目运行器
按钮
添加标签
,以便运行器可以使用匹配的执行器通过标签挑选作业。给出一些描述,然后点击创建运行器
按钮。这将重定向您到以下页面,您可以在步骤1中看到运行器注册命令。
从步骤1复制运行器注册命令,并使用以下docker compose命令登录到您的GitLab运行器容器。
docker compose exec -it gitlab-runner /bin/bash
一旦登录到运行器容器,将上述步骤1
中的命令粘贴到运行器容器内,并添加以下附加参数。
确保从您的步骤1中更新以下注册命令中的--token
值
gitlab-runner register --url http://localhost:8000
--token glrt-qL_FTjkAGqy7SHcYYStx
--executor docker
--name "Docker in Docker Runner"
--docker-image "docker:27.2.0"
--docker-privileged
--docker-volumes "/certs/client"
--docker-network-mode "gitlab-in-docker"
--clone-url "http://gitlab-server:8000"
我们将executor
设置为docker,这与我们上一篇文章
中的操作相同。然后给它一个有意义的名称并设置默认的docker镜像。我们在这里使用docker镜像docker:27.2.0
,以便在我们的流水线作业中运行docker命令时可以使用docker CLI。
为了启动构建和服务(docker in docker)容器,它使用privileged
模式。如果您想要使用Docker-in-Docker,您必须在您的Docker容器中始终使用privileged = true
。
我们还为服务和作业容器挂载了/certs/client
,这对于Docker客户端使用SSL证书以TLS模式连接是必需的。
最后,我们将网络设置为gitlab-in-docker
,这是我们的自定义网络,并将克隆URL设置为前面讨论的http://gitlab-server:8000
。
一旦您的命令准备就绪,按Enter
键,并在提示输入时继续按Enter
键,除非您想在提示时更新任何值。
查看运行器
按钮,您应该能看到包括您新注册的docker in docker运行器在内的所有运行器。.gitlab-ci.yml
。然后粘贴以下代码片段。
使用docker in docker构建:
stage: build
image: docker:27.2.0
services:
- docker:27.2.0-dind
variables:
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
tags:
- docker-in-docker
script:
- docker ps
- docker run -d --rm --name nested-container1-in-pipelinejob alpine sleep 20
- docker run -d --rm --name nested-container2-in-pipelinejob alpine sleep 20
- docker ps
- sleep 20
services: docker:27.2.0-dind
实际上是Docker官方提供的Docker in Docker服务。当我们为作业定义一个service
时,作业将首先等待该服务启动,一旦服务准备就绪,实际的作业容器将启动并处理作业的script
部分。
variables
将作为环境变量传递给作业容器,以便在运行docker CLI命令时从作业容器内访问docker引擎。DOCKER_TLS_CERTDIR
将设置SSL证书目录,而DOCKER_HOST
将通过SSL端口即2376
设置与docker引擎的默认连接。
如果您想不使用TLS连接,请按以下方式设置变量。
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
一旦docker in docker容器/服务准备就绪,执行器将开始通过拉取docker:27.2.0
镜像来启动作业容器,然后运行script
命令。
script
部分并开始运行这两个docker命令来运行docker容器- docker run -d –rm –name nested-container1-in-pipelinejob alpine sleep 20
- docker run -d –rm –name nested-container2-in-pipelinejob alpine sleep 20 这将在docker in docker服务内运行两个新容器。您可以通过登录到服务容器来确认这两个新容器
docker exec -it 0e7a68f4dfbf sh
0e7a68f4dfbf
是docker in docker容器的ID
然后运行以下命令以获取在dind服务内运行的所有容器。
docker --tlscacert=/certs/client/ca.pem
--tlscert=/certs/client/cert.pem
--tlskey=/certs/client/key.pem
--tlsverify=1
ps
结果应该看起来像这样。
gitlab runner
、job executor
)及其子容器彼此分离,与宿主机的docker引擎隔离。Docker in Docker的已知问题
Docker in Docker是推荐的配置,但GitLab文档在这里指出了某些已知问题点击查看 。
docker-compose
命令:在此配置中默认情况下不提供此命令。- 缓存:每个作业都在一个新的环境中运行。因为每个构建都通过其
services
获得Docker引擎的自己的实例,所以并发作业不会引起冲突。然而,作业可能会更慢,因为没有缓存层。
Docker执行器的替代方案
要在运行器上不启用privileged
模式或不挂载宿主机docker套接字的情况下构建Docker镜像,GitLab提供了以下两种替代方案,