docker - Docker-in-Docker GitLab CI 幽灵容器
问题描述
在我的组织中,我们使用 GitLab CI,我们的管道包含一个在 Docker 映像中运行的作业。
Job 在 Docker 镜像中运行一个脚本,该脚本本身会启动一个 Docker 容器以进行测试,这使得这成为 Docker-in-Docker 的情况。GitLab 作业定义与以下内容非常相似:
job:
image: docker:20.10.7
tags:
- our-custom-gitlab-runner-services
script:
# print some info
- docker ps
- docker network ls
# build and run
- docker network create my-net
- docker build -t my-image .
- docker run --rm --detach --net my-net --name my-container my-image
# test
# (run some tests here)
# cleanup
- docker stop my-container
- docker network rm my-net
现在这似乎工作了一段时间。我正在试验,我尝试删除--rm
标志和清理步骤,认为这并不重要,因为这项工作是独立的(哦,我错了)。
然后所有的地狱都崩溃了。
重新运行脚本后,docker ps
anddocker network ls
命令会在不应该出现的情况下显示my-container
并my-net
存在。在构建和运行部分之前添加额外的命令以删除这些工作作为一种解决方法,但docker ps
并docker network ls
在后续运行中重复显示这些重影。就像被创造出来之后它们现在永远存在一样。
问题是为什么会发生这种情况?对这篇文章的正确答案可以清楚地解释这种现象。
解决方案
这部分是因为您使用主机 docker 套接字安装作为 docker-in-docker 执行器机制。也就是说,您的作业直接连接到主机上的 docker 守护进程。
当您在作业中运行 docker 命令时,您将直接从作业容器与主机的 docker 守护进程进行通信。因此,GitLab 运行程序无法知道您创建了哪些容器或网络,甚至无法知道是否需要进行任何清理。它无法将您的作业创建的网络/容器与其他运行者或出于任何其他原因在主机上创建的容器区分开来。因此,GitLab Runner(明智地)不会做出任何努力来删除它没有直接创建的网络/容器。
一种可以防止这种情况发生的方法,这将使您的 docker-in-docker 构建更加封闭,是利用 dind 服务架构。不是将 docker 套接字直接安装到作业中,而是运行一个独立的 docker 守护程序作为作业的服务。这样,您的作业就有了自己的docker 守护进程,并且该守护进程由运行程序清理(当它清理时,您的作业创建的所有网络/容器也会这样做)。您必须相应地配置 GitLab 运行器和作业。这与GitLab 文档中的设置说明一起进行了进一步描述。
正确配置运行器后,作业定义可能如下所示:
myjob:
image: docker
services:
- docker:dind # <-- your own independent daemon!
variables:
# tell the docker client in your job
# to communicate with the service daemon
# instead of /var/run/docker.sock
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
script:
- docker network ls
# won't ever include my-net because
# it is destroyed along with the docker:dind service
# when your job ends!
- docker network create my-net
- docker info
# ...
这也是 docker-in-docker 与 GitLab 的更好设置,以使您的构建系统更安全并(帮助)防止作业逃离其容器。当不同的项目使用相同的底层主机时,这一点尤其重要。
推荐阅读
- php - 如何在位置天气搜索表单“API 支持阿拉伯语语言”中获取阿拉伯语结果
- linux - g_timeout_add 是线程安全的(Linux、GTK3、X11)吗?
- python-3.x - Python Webscraping with BeautifulSoup:它显示 0 而不是真实值
- scala - Gatling:如何在特定时间间隔后将用户数量翻倍?
- jenkins - Jenkins在运行多个jmeter脚本时出现内存不足错误
- regex - 需要 RE 才能在行尾前仅提取大写单词集
- html - 标注旁边的对齐按钮
- python - 计算列表中两个标记之间的子字符串数
- javascript - 检查 onClick 反应的值
- python - 集合操作数 ( | , & , - ,..etc) 是如何工作得这么快的?