【问题标题】:What is the result of mounting `/var/run/docker.sock` in a Docker in Docker scenario?在 Docker 场景中将 `/var/run/docker.sock` 挂载到 Docker 中的结果是什么?
【发布时间】:2020-08-01 21:23:08
【问题描述】:

我已阅读 Can anyone explain docker.sock 以了解 /var/run/docker.sock 的作用,但它在 GitLab CI 的 Use Docker socket binding 中的使用让我感到困惑。

这是他们的gitlab-runner注册示例命令:

sudo gitlab-runner register -n \
  --url https://gitlab.com/ \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

我看到生成的容器可以从两个地方获得docker

  1. unix 套接字/var/run/docker.sock
  2. 基础镜像docker:19.03.12中包含的docker二进制文件。

这不是PATH 冲突吗?我认为应该是其中之一,我可以从主机的 unix 套接字或基本映像中获得使用 docker 的能力。

我认为--docker-image 应该改为ubuntu:latest 或类似docker 不附带的内容,因为PATHdocker 已经来自主机套接字。或者,将移除 docker 套接字安装。

关于docker 的双重包含,这里实际发生了什么?

【问题讨论】:

  • 也许这会有所帮助:jpetazzo.github.io/2015/09/03/…
  • @DucNguyen Yup 帮助我了解了/var/run/docker.sock,但gitlab-runner 正在将 docker 套接字安装在 docker 映像中的 docker 顶部,而不是像您的链接中描述的那样作为替代方案。这就是问题所在。

标签: docker gitlab-ci gitlab-ci-runner unix-socket docker-in-docker


【解决方案1】:

Unix 套接字文件/var/run/docker.sock 通常由 Docker 守护进程创建。如果您将其他东西作为主容器进程运行,则不会创建套接字。你可以直接通过运行一个非Docker主进程的容器来查看,比如/bin/ls

docker run --rm docker:19.03.12 ls -l /var/run
docker run --rm docker:19.03.12 ls -l /run

/usr/bin/docker 二进制文件必须存在于容器文件系统中,如果您要使用它。容器永远不能调用主机上的二进制文件,套接字 API 也不会生成二进制文件。 (一些很早的“使用主机的 Docker 套接字”的帖子提倡将二进制文件绑定挂载到容器中,但这会导致库依赖问题,并使图像无法自包含。)

所以如果你真正需要的是一个 Docker 容器,带有一个 docker 二进制文件,它可以调用主机的 Docker 套接字,你需要一个像 docker 这样的图像,其中 图像 有一个 @ 987654328@,另外还需要绑定挂载主机的/var/run/docker.sock到容器中。

docker run \
  --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  docker:19.03.12 \
  docker ps

您链接到的 GitLab 设置似乎相当做作。使用docker 映像运行作业意味着几乎唯一 构建步骤可以运行的是docker 命令。在技​​术层面上,如果没有 docker 二进制文件并访问正在运行的 Docker 守护程序,您将无法启动 docker 容器;该页面顶部描述的 shell-executor 方法似乎更简单,并且没有任何缺点。

您还可能会发现拥有构建时依赖项(编译器、头文件、静态检查工具等)的 Docker 映像很方便。这将允许您更新这些依赖项,而无需对整个构建集群进行更新。如果您的构建脚本本身需要调用docker,那么您的构建工具映像需要安装Docker,只需使用普通的RUN apt-get install 命令即可。你需要以同样的方式将宿主机的 Docker 套接字推送到容器中,因此你不需要启动单独的 Docker 守护进程。

【讨论】:

  • (我不认为你描述的设置是“Docker-in-Docker”。我习惯这个词的意思是“在容器中运行 Docker 守护程序”,而不是“在访问主机的 Docker 守护进程的容器中运行 docker 二进制文件”。您链接到的页面描述了 Docker-in-Docker 设置,就在您提到的特定锚点上方。)
  • 很好的答案。如果我运行docker run --rm docker:19.03.12 docker ps(因此没有套接字安装),则会出现有关 docker TCP 查找失败的错误。我认为因为docker ps 是这里的主要进程(而不是像ls 这样的东西),所以会创建套接字,并且 docker 查找将解析为内部创建的套接字。我在这里错过了什么?
  • 关于最后一段,如果我使用apt-get install 安装docker,我就不必从基础docker:* 图像继承,对吧?我只会做插座安装和apt-get install?
  • 如果你docker run docker docker ps,容器中运行的唯一进程是Docker客户端二进制;它不会自动启动守护进程。 (以同样的方式docker run nginx sh 运行交互式 shell 而不是 Nginx 服务器。)
  • 是的,如果您有一个基于 Debian 的映像和 RUN apt-get install docker.io,那么会将 /usr/bin/docker 二进制文件放入您的映像中,并且您不需要特别扩展 docker 映像,但是运行容器时需要绑定挂载 Docker 套接字。
【解决方案2】:

首先,您需要了解 docker 的工作原理,以便了解此流程,docker 有一个服务器和一个客户端 docker-clidocker daemon,客户端使用 APIS 与 docker 守护进程通信。

docker.sock 是确保 docker 客户端和守护进程(服务器)之间连接的 UNIX 套接字。

由于 docker 容器不像虚拟机那样没有kernel,所以在 docker 中运行的每个容器都使用主机的内核并在主机的内核之上构建容器。 容器本身没有内核,因此除非您使用主机的内核,否则您无法在 docker 内部构建 docker。

gitlab-runner 有很多执行器:shell ssh docker 等等 ...

使用 docker 执行器意味着运行器将创建一个容器,然后将您的 repo 克隆到该容器中并运行您传递的脚本,然后销毁该容器。

gitlan-runner 需要一个基础镜像来创建运行脚本的容器。您不必使用 docker:19.03.12 或挂载 /var/run/docker.sock 卷,除非您的脚本具有 docker 命令(或者通常您需要访问 docker )并且这两种策略都不同,您应该知道安装 @987654332 @ 不是 docker 中的 docker。

为了在 docker 中实现 docker,您需要将 --privileged 标志添加到容器中,这基本上使容器中的 root 成为主机上的完整 root。它可以管理内核参数,它具有所有功能。

这里有一个很好的reference 关于这个主题

【讨论】:

    猜你喜欢
    • 2019-08-14
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 2020-01-03
    • 2019-09-27
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    相关资源
    最近更新 更多