卖兜搞IT

Docker Daemon的Unix Socket和TCP Socket

首先欢迎大家去购买我在慕课网的Docker课程,购买链接请点击微信公众号底部阅读原文

因为有不少同学问及Docker Daemon(dockerd) 和 docker.sock, 所以这里就通过这篇文章再给大家解释一下。

关于socket

Docker是CS架构,客户端(也就是Docker的CLI)和服务器端(也就是dockerd)进行通信的方式有两种:

•单机默认情况是通过Unix socket (IPC,是通过文件进行通信的)•多机情况下(比如Docker客户端和dockerd不在一台机器上),那就可以打开TCP socket,通过网络进行通信

Image

Unix Socket

至于为什么默认使用Unix socket,关闭TCP socket,原因主要是为了安全。Unix socket是文件系统里的一个文件,在Linux中,文件是很容易 通过设置权限来做访问控制的,当我们启动了dockerd进程后,会在 /var/run 目录下产生一些文件,其中有一个文件是 docker.sock , 这个文件的权限是root权限,docker这个group的。

$  run pwd/var/run$  run lsWSL  lock  mount  resolvconf  shm  sudo  user$  run sudo service docker start*StartingDocker: docker                                                                                       [ OK ]$  run lsWSL  docker  docker-ssd.pid  docker.pid  docker.sock  lock  mount  resolvconf  shm  sudo  user  xtables.lock$  run ls -l | grep dockerdrwx------6 root root   160Aug1313:10 docker-rw-r--r--1 root root     4Aug1313:10 docker-ssd.pid-rw-r--r--1 root root     3Aug1313:10 docker.pidsrw-rw----1 root docker   0Aug1313:10 docker.sock

这就是为什么我们在使用docker命令的时候,需要加 sudo 或者把当前用户添加到 docker这个组里。

sudo gpasswd -a $USER dockersudo service docker restart

docker.sock的一个小实验

任何能读取docker.sock文件的程序,实际上就能通过docker客户端做所有docker命令能做的事情,利用这个特点我们可以做一些有趣但某些场景可能很 有用的事情。比如现在有一个container

➜~ docker container run -d -p 8080:80 nginx7ef76822c12f4ebd66eb24ca50e8848df0da5110ffc1c32753342daf96eb203e➜~➜~ docker container psCONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES7ef76822c12f   nginx     "/docker-entrypoint.…"5 seconds ago   Up4 seconds   0.0.0.0:8080->80/tcp,:::8080->80/tcp   vibrant_vaughan➜~

我们可以再创建一个container,把本地的 docker.sock 文件给mount进去, 只要这个container里安装了docker客户端,那它就能访问到这个文件, 从而做任何我们在宿主机上docker命令可以做的事情。拉取一个安装了docker客户端的镜像

docker pull docker

创建容器并加载 docker.sock文件。这时候我们在这个容器里就可以运行docker命令了,比如创建容器,而且这个容器是创建在了宿主机上,而不是这个container里。

➜~ docker container run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker:latest sh/#/#/# docker container psCONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS                                   NAMES3e72e6a9563d   docker:latest   "docker-entrypoint.s…"14 seconds ago   Up14 seconds                                           tender_kilby7ef76822c12f   nginx           "/docker-entrypoint.…"4 minutes ago    Up4 minutes    0.0.0.0:8080->80/tcp,:::8080->80/tcp   vibrant_vaughan/#/# docker container run --rm -d busybox:latest ping 1.1.1.1b250c29051e51cb429e15471ed301c0806a29cef1ffbf388c46861a7f538f4f9/#/# docker container lsCONTAINER ID   IMAGE            COMMAND                  CREATED              STATUS              PORTS                                   NAMESb250c29051e5   busybox:latest   "ping 1.1.1.1"4 seconds ago        Up4 seconds                                                stoic_agnesi3e72e6a9563d   docker:latest    "docker-entrypoint.s…"About a minute ago   UpAbout a minute                                           tender_kilby7ef76822c12f   nginx            "/docker-entrypoint.…"5 minutes ago        Up5 minutes        0.0.0.0:8080->80/tcp,:::8080->80/tcp   vibrant_vaughan/#/# exit➜~➜~ docker container lsCONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS         PORTS                                   NAMESb250c29051e5   busybox:latest   "ping 1.1.1.1"10 seconds ago   Up9 seconds                                           stoic_agnesi7ef76822c12f   nginx            "/docker-entrypoint.…"5 minutes ago    Up5 minutes   0.0.0.0:8080->80/tcp,:::8080->80/tcp   vibrant_vaughan➜~

像这种模式一般用于 本地容器的监控,log采集等,因为它有这个全局的视角,只要在这个容器里安装好相应的程序就可以了。

TCP Socket

但是有些情况下,我们想使用本地的docker客户端去访问远程的dockerd,这时候就需要打开TCP socket了,通过IP + 端口的形式对外提供服务。如果要打开TCP socket,则可以通过下面类似的命令实现

# listen using the default unix socket, and on 2 specific IP addresses on this host.$ sudo dockerd -H unix:///var/run/docker.sock -H tcp://192.168.59.106 -H tcp://10.10.10.2

然后在客户端设置一下docker host的位置就可以了(默认端口是2375)

$ export DOCKER_HOST="tcp://0.0.0.0:2375"$ docker ps

具体可参考 https://docs.docker.com/engine/reference/commandline/dockerd/

至于安全性,大家就非常清楚了,任何人只要能访问到你的IP和端口,那就能连接你的dockerd,做任何你本地能做的事情。

最后希望本文能帮助到大家,哪怕一点点。