一文带你搞懂 Docker In Docker(DinD) 模式下的资源管理
公众号关注「奇妙的 Linux 世界」设为「星标」,每天带你玩转 Linux !今天遇到了一个群友关于 Docker DinD 的问题。有人熟悉docker in docker么 请教个问题, 我现在在docker-1里面挂载了本地的/root/.m2 想在里面启动一个新的docker在build的时候使用 这个目录下的缓存 有人做过么~需求是想要通过容器1启动容器2, 同时要求容器2...
公众号关注 「奇妙的 Linux 世界」
设为「星标」,每天带你玩转 Linux !
今天遇到了一个群友关于 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 引擎。
本机操作
我们从 本机操作 开始, 一步步扩展开, 比较容易理解
从图中可以看到, 当 cli 和 sock 都在本机的时候, 所有注入的 环境依赖(变量、路径挂载、端口映射等) 都是直接使用 宿主机 的。
这个时候的认知最简单。
启动
$ docker run -d --rm --name docker-dind-nginx-local nginx:alpine
6acd48977a82ed7fcbc0f3e2f9ae8b84675bfb7a26b9a2a27c36068b641d2fb1
远程操作
同时 Docker 还提供了远程操作方式。
这个时候保证本机的 docker 引擎 未安装 或者 未启动, 以避免产生理解歧义。
当在 cli 的机器上, 配置 DOCKER_HOST
变量的时候, 就可以实现远程的 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
到 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」,原文:https://url.hi-linux.com/LAEOs,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。
最近,我们建立了一个技术交流微信群。目前群里已加入了不少行业内的大神,有兴趣的同学可以加入和我们一起交流技术,在 「奇妙的 Linux 世界」 公众号直接回复 「加群」 邀请你入群。
你可能还喜欢
点击下方图片即可阅读
五分钟搞懂 Docker 与 Kubernetes 的关系与区别
点击上方图片,『美团|饿了么』外卖红包天天免费领
更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)