公众号关注「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

docker.sock_docker.sock_docker.sock

今天遇到了一个群友关于 Docker DinD 的问题。

有人熟悉docker in docker么 请教个问题, 我现在在docker-1里面挂载了本地的/root/.m2 想在里面启动一个新的docker在build的时候使用 这个目录下的缓存 有人做过么~

需求是想要通过容器1启动容器2, 同时要求容器2也能挂载并使用.m2目录, 加入 JAVA 的应用的构建。

其实 DinD 说通了并不难。想来难的地方应该也就是理不清楚各个容器之间的关系

Docker 常规操作模式

首先抽象一下 Docker 的操作, 提出两个重点组件

docker.sock:/var/run/docker.sock。套接字, 为用户提供管理 docker 引擎的接口。

docker CLI:命令行工具。面向用户提供语义化的接口操作方式。

任何符合docker.sock通信的方式和操作, 都能控制 docker 引擎。

本机操作

我们从本机操作开始, 一步步扩展开, 比较容易理解

docker.sock_docker.sock_docker.sock

从图中可以看到, 当 cli 和 sock 都在本机的时候, 所有注入的环境依赖(变量、路径挂载、端口映射等)都是直接使用宿主机的。

这个时候的认知最简单。

启动

$ docker run -d --rm --name docker-dind-nginx-local nginx:alpine

6acd48977a82ed7fcbc0f3e2f9ae8b84675bfb7a26b9a2a27c36068b641d2fb1

远程操作

同时 Docker 还提供了远程操作方式。

这个时候保证本机的 docker 引擎未安装或者未启动, 以避免产生理解歧义。

当在 cli 的机器上, 配置DOCKER_HOST变量的时候, 就可以实现远程的 sock 操作。

docker.sock_docker.sock_docker.sock

设置环境变量, 指定远程宿主机

export DOCKER_HOST=ssh://root@192.168.100.100

本地执行查看命令

$ docker ps |grep docker-dind

6acd48977a82   nginx:alpine "/docker-entrypoint.…"   47 seconds ago   Up 44 seconds   80/tcp  docker-dind-nginx-local

本地启动容器

$ docker run -d --rm --name docker-dind-nginx-remote nginx:alpine

c5b898d652ce1e9eb4d307501c36fd2aa9e9c64931eff59eb4458bdf4b092ec0

登陆到远程宿主机, 查看所启动的容器

$ docker ps |grep docker-dind

c5b898d652ce   nginx:alpine    "/docker-entrypoint.…"   About a minute ago   Up 59 seconds   80/tcp    docker-dind-nginx-remote
6acd48977a82   nginx:alpine    "/docker-entrypoint.…"   4 minutes ago        Up 4 minutes    80/tcp    docker-dind-nginx-local

可以看到, 本地操作远程是完全没有问题的。

注意由于本地没有安装 docker 引擎, 且只下载了一个 cli 命令行工具。所以在注入环境依赖的时候, 通常也不会造成困惑, 会默认使用宿主机资源。

除此之外, Docker 还提供了HTTPS接口的远程操作方式。这里就不讨论了。不过额外强调一句,如果要开这种模式, 一定要配置证书和身份验证, 否则不小心开到公网, 就是被别人当成木马马场用。

Docker DinD 模式

所谓的Docker-in-Docker模式, 就是将docker.sock挂载到启动的容器A中, 而容器A提供操作方式/界面(例如 cli 命令工具)

在宿主机执行 docker:dind 容器, 并挂载docker.sock到容器中

docker run --rm -it --name=container01 -v /var/run/docker.sock:/var/run/docker.sock docker:dind sh

docker.sock_docker.sock_docker.sock

通过上图可以看到, 我们通过挂载docker.sock到 container01 中后, 相当于在 container01 中同时拥有了docker.sock和docker cli, 这种情况和本地操作类似。

这里就是困惑点:当我在 container01 中新启动一个容器的时候, 此时如果需要挂载资源(例如映射文件目录), 应该使用container01的路径?还是宿主机的路径?

在容器中执行docker run命令, 启动一个新容器

container01 # docker run -d --rm --name docker-dind-nginx-inside nginx:alpine

786b0c555e7ba80c56638e65fb088252316d80699b6936549667c79c7637d4c2

重新看图,其实这点很简单了。

虽然是是在 container01 中执行的docker run命令, 但是调用的docker.sock套接字是从宿主机挂载到container01中的。

因此实际上还是通过宿主机启动的container02。换句话说,

container02的父节点是宿主机

contaienr02和container01是兄弟关系。

在container01中, 通过命令我们之前启动的三个容器。

container01 # docker ps |grep docker-dind

786b0c555e7b   nginx:alpine     "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   80/tcp    docker-dind-nginx-inside
c5b898d652ce   nginx:alpine     "/docker-entrypoint.…"   40 hours ago    Up 40 hours    80/tcp    docker-dind-nginx-remote
6acd48977a82   nginx:alpine     "/docker-entrypoint.…"   40 hours ago    Up 40 hours    80/tcp    docker-dind-nginx-local

另外一种 DinD

如果有人说, 我启动container01的时候不挂载docker.sock, 而是直接在 contianer01 中完整安装一个 docker 引擎。这种情况应该怎么挂载呢?

如果是在container01中执行的的启动命令, 这个时候肯定就是挂在 container01 对应的路径。

不过,不得不强调一下这种把容器当成虚拟机的用法, 还是敬而远之吧。

总结

其实很简单, 就一句话:谁执行容器的启动, 就挂载谁的路径。

思考题

我们知道在 k8s 中, 简略的调度过程是这样的user -> master api-server -> node kubelet -> docker.sock/containerd.sock。

那么, 用户在任意地方启动 pod 的时候, 如果需要挂载 node 的目录资源到 pod 中, 应该是用 *用户所在机器的目录路径?master 节点路径?还是 node 节点路径?

本文转载自:「熊猫云原生Go」,原文:,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。

最近,我们建立了一个技术交流微信群。目前群里已加入了不少行业内的大神,有兴趣的同学可以加入和我们一起交流技术,在 「奇妙的 Linux 世界」 公众号直接回复 「加群」 邀请你入群。

你可能还喜欢

点击下方图片即可阅读

五分钟搞懂 Docker 与 Kubernetes 的关系与区别

点击上方图片,『美团|饿了么』外卖红包天天免费领

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注