docker 的 /var/run/docker.sock 参数
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
关于/var/run/docker.sock 参数
在创建 docker 容器时,有时会用到 /var/run/docker.sock 这样的数据卷参数,例如以下 docker-compose.yml,可以看到 kafka 容器的数据卷参数带有 /var/run/docker.sock :
本文要聊的就是这个/var/run/docker.sock 参数。
注:关于上述 docker-compose.yml 的作用和相关实战,请参考《kafka的Docker镜像使用说明(wurstmeister/kafka)》;
预备知识
搞清楚/var/run/docker.sock 参数的前提是了解 docker 的 client+server 架构,如下是执行 docker version 命令的结果:
可见在电脑上运行的 docker 由 client 和 server 组成,我们输入 docker version 命令实际上是通过客户端将请求发送到同一台电脑上的 Doceker Daemon 服务,由 Docker Daemon 返回信息,客户端收到信息后展示在控制台上,来自 stack overflow 的架构图如下:
做好了准备工作就可以进入正题了。
官方解释
从下面这个官方文档看起,地址是:https://docs.docker.com/v17.09/engine/reference/commandline/dockerd/#description
上图是 Docker Daemon 的配置参数,红框处可见 daemon 默认监听的是/var/run/docker.sock 这个文件,所以 docker 客户端只要把请求发往这里,daemon 就能收到并且做出响应。
按照上面的解释来推理:我们也可以向/var/run/docker.sock 发送请求,也能达到 docker ps、docker images 这样的效果;
好吧,来试试!
向 Docker Daemon 发送请求
为了验证 Docker Daemon 可以通过/var/run/docker.sock 接收请求,我们用 curl 命令来验证,测试环境如下:
操作系统:CentOS Linux release 7.6.1810
Docker: 1.13.1
接下来开始动手验证:
执行 docker image 命令看本地有哪些镜像:
可见有 tomcat 和 nginx 两个镜像;
执行 docker ps 命令看本地有哪些正在运行的容器:
可见只运行了一个 tomcat 容器;
执行以下命令,可以直接发 http 请求到 Docker Daemon,获取本地镜像列表,等同于 docker image :
收到的响应是 JSON,格式化后如下所示,可见通过/var/run/docker.sock 向 Docker Daemon 发送请求是没有问题的:
执行以下命令,可以直接发 http 请求到 Docker Daemon,获取运行中的容器列表,等同于 docker ps :
收到的响应是 JSON,格式化后如下所示:
更多与 Docker Daemon 交互的请求信息请参考官方文档:https://docs.docker.com/engine/api/v1.39 ,信息很全面,如下图:
至此,我们对 docker 的 client、server 架构有了清楚的认识:Docker Daemon 相当于一个 server,监听来自 /var/run/docker.sock 的请求,然后做出各种响应,例如返回镜像列表,创建容器。
顺便搞清楚一个常见问题
有个常见的问题相信大家都遇见过,执行 docker 命令时控制台报错如下:
此时的您一定很清楚问题原因了:Docker Daemon 服务不正常,所以客户端发送请求得不到响应
用 systemctl status docker 命令看看 Docker Daemon 状态,应该是停止或报错:
如果是停止状态,执行 systemctl start docker 启动服务即可,如果是错误就要 case by case 去分析了。
开篇问题
再回到文章开篇处的问题,启动容器时的数据卷参数"/var/run/docker.sock:/var/run/docker.sock"有什么用?相信您已经猜到了:
宿主机的 /var/run/docker.sock 被映射到了容器内,有以下两个作用:
在容器内只要向/var/run/docker.sock 发送 http 请求就能和 Docker Daemon 通信了,可以做的事情前面已经试过了,官方提供的 API 文档中有详细说明,镜像列表、容器列表这些统统不在话下;
如果容器内有 docker 文件,那么在容器内执行 docker ps、docker port 这些命令,和在宿主机上执行的效果是一样的,因为容器内和宿主机上的 docker 文件虽然不同,但是他们的请求发往的是同一个 Docker Daemon;
基于以上结论,开篇问题中的镜像 wurstmeister/kafka:2.11-0.11.0.3 既然用到了/var/run/docker.sock 参数,那么该容器应该会向 Docker Daemon 发送请求,接下来我们尝试着分析一下,看看能否证实这个推测;
证实推测
去镜像的官网找到容器启动时自动执行的脚本 start-kafka.sh,地址是:https://github.com/wurstmeister/kafka-docker/blob/0.10.0/start-kafka.sh ,如下图红框所示,果然有用到 docker 客户端,执行的是 docker port 命令:
上图红框中的功能:通过 docker port 命令得到该容器的端口映射信息,再通过 sed 命令从该信息中取得端口号,然后再用 export 命令暴露出去。
还剩最后一个问题:上图红框中的 docker 命令在容器中可以执行么?会不会提示"找不到 docker 命令"?对于这个问题,我的猜测是该镜像已经包含了可执行文件"docker",所以去看看该镜像的 Dockerfile 文件吧,地址是:https://github.com/wurstmeister/kafka-docker/blob/0.10.0/Dockerfile 如下图红框,果然在构建镜像的时候就安装了 docker 应用,因此在容器中执行 docker xxx 命令是没问题的:
至此,所有理论上的推测都找到了直接证据,可以动手验证:进 kafka 容器内试试 docker 命令。
验证上述分析
首先确保您的电脑上 docker、docker-compose 都已经装好可以正常使用;
创建名为 docker-compose.yml 的文件,内容如下(其实就是开篇贴出的那个):
在 docker-compose.yml 所在目录执行命令 docker-compose up -d 创建容器:
执行以下命令进入 kafka 容器:
在容器内执行命令 docker ps ,看到的内容和在宿主机上执行 docker ps 命令是一样的:
可见容器内的 docker 客户端发出的请求的确是到达了宿主机的 Docker Daemon,并且收到了响应。
在容器内执行命令 ps -ef|grep docker ,没有结果,证明容器内没有 Docker Daemon 服务在运行,在宿主机执行此命令可以看到如下内容,证明宿主机上的 Docker Daemon 服务是正常的:
优化建议
目前我们 docker 的 client、server 架构已经比较清楚了,对开篇的问题也找到了答案,不过细心的您是否注意到一个问题,如下图,这是 kafka 镜像的 Dockerfile 文件:
上图显示 kafka 镜像中安装了 docker 应用,这里面包含了 client 和 daemon,但实际上只用到了 client,这样是否有些浪费呢?如果以后我们制作镜像的时候要用到 docker 客户端,难道我们的镜像也要这样把整个 docker 应用装好么?
一篇来自官方的文档给我们了启发,地址是:https://docs.docker.com/docker-for-azure/upgrade/ ,如下图红框所示,将宿主机的可执行文件 docker 映射到容器的/usr/bin 目录下,这样容器启动后就可以直接执行 docker 命令了:
至此,对 docker 的/var/run/docker.sock 参数的学习和实战就全部完成了,希望本文能帮助您加深对 docker 的理解,灵活的使用该参数可以助您设计出更强大的 docker 镜像。
再加一句:现在您可以去了解 Docker in Docker 了,相信您会学得很轻松愉快。
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/f0bdb9eb2aba7ff061ee1442a】。文章转载请联系作者。
评论