Docker执行器与Docker DIND镜像

7

我是gitlabci的新手。我想了解为什么在GitLab CI作业中构建Docker镜像需要使用docker dind镜像,为什么不能在脚本下使用docker executor并运行docker命令?

当我们注册docker executor gitlab runner时,我们选择一个镜像。再次在gitlabci中,在image:services:字段下选择一个镜像。这是否意味着该GitLab CI作业容器在docker executor容器内运行?

1个回答

12

为什么在GitLab CI作业中构建Docker镜像需要使用Docker DIND镜像?为什么不能使用Docker执行程序并在脚本下运行Docker命令?

这部分取决于您如何配置GitLab Runner。

为什么在容器内无法使用docker

当您调用docker命令时,它们实际上是在和一个Docker 守护进程交互,该守护进程需要执行构建和执行其他docker命令。通常,在Docker执行程序下运行的作业默认情况下没有访问任何Docker守护进程。这与您尝试在本地启动的Docker容器内运行docker时遇到的问题相同。

即使我可以在主机上成功运行docker

$ docker run --rm docker /bin/sh -c 'hello from container $HOSTNAME'
hello from container 2b51479b11b1

我无法在容器内运行 docker

$ docker run --rm docker /bin/sh -c 'docker info'
errors pretty printing info
Client:
 Context:    default
 Debug Mode: false

Server:
ERROR: error during connect: Get "http://docker:2375/v1.24/info": dial tcp: lookup docker on 192.168.65.5:53: no such host

尝试运行任何其他重要的Docker命令(例如buildrun等)将导致相同的错误。

唯一的例外是,如果您将GitLab runner配置为在特权模式下运行容器并将/var/run/docker.sock挂载到所有作业中(这不是建议),则所有作业都可以直接与主机上的Docker守护程序通信。另一个例外可能是,如果您使用shell执行程序,并且在运行runner的主机上安装了docker,则也可能出现此情况。

dind服务如何解决这个问题

docker:dind服务是仅为您的作业创建的守护程序。这非常重要,因为它可以防止并发作业互相干扰或能够升级访问权限。

当构建开始时,GitLab runner将创建两个容器:作业容器和docker:dind容器; 它们链接在一起。当您的作业调用docker命令时,您的作业连接到docker:dind容器,后者执行所请求的命令。

由您的作业创建的任何容器(例如,通过作业的docker rundocker build调用)由运行在docker:dind容器上的守护程序管理,而不是主机守护程序。如果在作业内部运行docker ps,您将注意到没有在主机上运行的容器。此时,尽管如果您在主机上运行docker ps,您将看到作业容器、dind容器和任何其他正在运行的容器。


为了澄清您的其他问题:

当我们注册具有Docker执行程序的GitLab runner时,我们选择一个映像

在您的runner配置中指定的镜像仅是要使用的默认Docker镜像,如果作业未声明任何image:键,则使用该镜像。它不会以任何方式影响runner的运行。

在gitlabci中,我们在image:或services:字段下选择一个映像

当Docker执行程序运行作业时,它使用docker run来运行作业。 image:键确定要用于运行作业的镜像。类似地,services:定义用于服务容器的镜像——服务容器是作业容器的同级,并且与links连接。

那是否意味着这个GitLab CI作业容器在docker执行程序容器内运行?

不是。我还想澄清:runner / executor并不一定在容器中运行。Runner可以安装为Windows服务,或者甚至直接在系统上运行的进程。您可以使用恰好位于容器内的runner,但它不会实质性地影响作业如何运行。

无论如何,运行作业的容器通常始终由主机Docker守护程序直接运行。


1
我有点困惑。CI能否以某种方式配置,使得Runner直接在主机上运行,而不是在任何容器中运行,那么如果作业没有指定镜像,则Docker构建命令不需要使用dind,对吗?我认为在大多数情况下,建议Runner在Docker中运行,以实现隔离等功能?我是日常用户,但从未担任过GitLab CI管理员。 - Lei Yang
2
@LeiYang 如果使用 docker 执行器运行作业,则该作业将始终在容器中运行。如果您希望作业直接在主机上运行,则应使用 shell 执行器 类型。 - sytech
1
如果一个Docker/Bash执行器运行一个作业,这是由GitLab CI管理员配置决定的,还是可以在gitlab-ci.yml中指定? - Lei Yang
2
@LeiYang 运行管理员完全决定执行者类型。项目用户无法更改执行者类型。项目对此唯一的控制方式是通过 (1) 在作业中指定“tags:”(但这需要事先注册具有指定标签的运行程序),和/或者(2) 注册专用于该项目的项目锁定运行程序(如果使用未标记的作业,则禁用共享运行程序)。 - sytech
非常感谢 @sytech。我已经搞清楚我的问题了。 - Rad4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接