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

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

02f1b72cf1fcaea98e18d45481a0c86a.png

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

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

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

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

Docker 常规操作模式

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

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

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

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

本机操作

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

3d3282aa688dc236e2b1cf90cb0d59e2.jpeg

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

这个时候的认知最简单。

启动

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

6acd48977a82ed7fcbc0f3e2f9ae8b84675bfb7a26b9a2a27c36068b641d2fb1

远程操作

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

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

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

f2b2b6262b002739efe64c9c24ebb722.jpeg

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

$ 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
9eb14f7fefdca3c316696e7b864372b1.jpeg

通过上图可以看到, 我们通过挂载 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

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

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

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

  3. container02 的父节点是 宿主机

  4. 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。

2e5e04f501b4145fd727c69ffdbebba4.gif

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

3489bcc6a1a48182641214e06c462efb.png

你可能还喜欢

点击下方图片即可阅读

10d4e8cd7eb526b8a4bbc20882e72944.jpeg

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

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

2fd1b1f35ce1a659645c91033a3a11ce.png

更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐