公众号关注「奇妙的 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」,原文:,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。
最近,我们建立了一个技术交流微信群。目前群里已加入了不少行业内的大神,有兴趣的同学可以加入和我们一起交流技术,在 「奇妙的 Linux 世界」 公众号直接回复 「加群」 邀请你入群。
你可能还喜欢
点击下方图片即可阅读
五分钟搞懂 Docker 与 Kubernetes 的关系与区别
点击上方图片,『美团|饿了么』外卖红包天天免费领
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777