预备知识
搞清楚/var/run/docker.sock参数的前提是了解docker的client+server架构,如下图
可见在电脑上运行的docker由client和server组成,我们输入docker version命令实际上是通过客户端将请求发送到同一台电脑上的Doceker Daemon服务,由Docker Daemon返回信息,客户端收到信息后展示在控制台上。
可是这个又跟docker.sock有什么关系呢?别急,我们再了解一下docker一些比较重要的组件
Docker 的主要组件
安装 docker ,其实是安装了 docker 客户端、dockerd 等一系列的组件,其中比较重要的有下面几个。
Docker CLI(docker)
docker 程序是一个客户端工具,用来把用户的请求发送给 docker daemon(dockerd)。
该程序的安装路径为:
1 | /usr/bin/docker |
Dockerd
docker daemon(dockerd),一般也会被称为 docker engine。
该程序的安装路径为:
1 | /usr/bin/dockerd |
Containerd
在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。
该程序的安装路径为:
1 | /usr/bin/docker-containerd |
Containerd-shim
它是 containerd 的组件,是容器的运行时载体,主要是用于剥离 containerd 守护进程与容器进程,引入shim,允许runc 在创建和运行容器之后退出,并将 shim 作为容器的父进程,而不是 containerd 作为父进程,这样做的目的是当 containerd 进程挂掉,由于 shim 还正常运行,因此可以保证容器不受影响。此外,shim 也可以收集和报告容器的退出状态,不需要 containerd 来 wait 容器进程。我们在 docker 宿主机上看到的 shim 也正是代表着一个个通过调用 containerd 启动的 docker 容器。
该程序的安装路径为:
1 | /usr/bin/docker-containerd-shim |
RunC
RunC 是一个轻量级的工具,它是用来运行容器的,容器作为 runC 的子进程开启,在不需要运行一个 Docker daemon 的情况下可以嵌入到其他各种系统,也就是说可以不用通过 docker 引擎,直接运行容器。docker是通过Containerd调用 runC 运行容器的
该程序的安装路径为:
1 | /usr/bin/docker-runc |
从 hello world 开始
我们通过hello-world镜像分析来进行:
1 | [vagrant@docker-host docker]$ docker run hello-world |
上面的输出信息指出,hello-world 容器的运行经历了如下四步:
- Docker 客户端向 docker daemon 发送请求
- Docker daemon 从 Docker Hub 上拉取镜像
- Docker daemon 使用镜像运行了一个容器并产生了输出
- Docker daemon 把输出的内容发送给了 docker 客户端
这是一个很抽象也很容器理解的过程,但是我们还想知道更多:docker daemon 是如何创建并运行容器的?
其实容器部分的操作和管理都被 dockerd 外包给 containerd 了,下图描述了运行一个容器时各个组件之间的关系:
进入正题
Docker Daemon 的连接方式
UNIX 域套接字
默认就是这种方式, 会生成一个
/var/run/docker.sock
文件,UNIX
域套接字用于本地进程之间的通讯, 这种方式相比于网络套接字效率更高, 但局限性就是只能被本地的客户端访问。tcp 端口监听
服务端开启端口监听
dockerd -H IP:PORT
, 客户端通过指定IP和端口访问服务端docker -H IP:PORT
。通过这种方式, 任何人只要知道了你暴露的ip和端口就能随意访问你的docker服务了, 这是一件很危险的事, 因为docker的权限很高, 不法分子可以从这突破取得服务端宿主机的最高权限。
什么是unix socket?
unix socket可以让一个程序通过类似处理一个文件的方式和另一个程序通信,这是一种进程间通信的方式(IPC)。
当你在host上安装并且启动好docker,docker daemon
会自动创建一个socket文件并且保存在/var/run/docker.sock
目录下。docker daemon
监听着socket中即将到来的链接请求(可以通过-H unix:///var/run/docker.sock
设定docker daemon
监听的socket文件,-H参数还可以设定监听tcp:port或者其它的unix socket),当一个链接请求到来时,它会使用标准IO来读写数据。
docker.sock 是docker client 和docker daemon 在localhost进行通信的socket文件。
可以直接call这个socket文件来拉去镜像,创建容器,启动容器等一系列操作。(其实就是直接call docker daemon API而不是通过docker client的方式去操控docker daemon)。
官方说明
我们从Docker Daemon进行,查看它的官方文档
上图是Docker Daemon的配置参数
翻译过来就是:–host=[]指定Docker守护程序将在何处侦听客户端连接。如果未指定,则默认为/var/run/docker.sock
所以docker客户端只要把请求发往这里,daemon就能收到并且做出响应。
按照上面的解释来推理:我们也可以向/var/run/docker.sock
发送请求,也能达到docker ps
、docker images
这样的效果;
验证
1.查看镜像:
docker-cli方式:
1
2
3
4
5
6[vagrant@docker-host ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
spring_demo latest b7c0355e0a01 6 days ago 151MB
nginx latest f35646e83998 2 weeks ago 133MB
hello-world latest bf756fb1ae65 9 months ago 13.3kB
ampregistry:5000/sng-biz-base-alpine 2.1.0 54c2c81fffbe 17 months ago 137MB请求到Docker Daemon:
该请求返回的是json串,使用
| jq .
是为了格式化json,方便查看jq是linux里面的一个json格式化工具,如果没有安装可以去掉后面的
| jq .
代码,拷贝返回的json串手动格式化也可以1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52[vagrant@docker-host ~]$ curl -s --unix-socket /var/run/docker.sock http:/images/json | jq .
[
{
"VirtualSize": 151316494,
"Size": 151316494,
"Containers": -1,
"Created": 1603359433,
"Id": "sha256:b7c0355e0a01f296e6ac94071b19c227839c8c19fecb2376dd8677ecbbe48017",
"Labels": null,
"ParentId": "sha256:4a5e4dd8fb964affb9750f01f66fb5f381988fcdbf8928902ce3f77b14fe990a",
"RepoDigests": null,
"RepoTags": [
"spring_demo:latest"
],
"SharedSize": -1
},
{
"VirtualSize": 132861270,
"Size": 132861270,
"Containers": -1,
"Created": 1602578384,
"Id": "sha256:f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35",
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"ParentId": "",
"RepoDigests": [
"nginx@sha256:ed7f815851b5299f616220a63edac69a4cc200e7f536a56e421988da82e44ed8"
],
"RepoTags": [
"nginx:latest"
],
"SharedSize": -1
},
{
"VirtualSize": 13336,
"Size": 13336,
"Containers": -1,
"Created": 1578014497,
"Id": "sha256:bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b",
"Labels": null,
"ParentId": "",
"RepoDigests": [
"hello-world@sha256:8c5aeeb6a5f3ba4883347d3747a7249f491766ca1caa47e5da5dfcf6b9b717c0"
],
"RepoTags": [
"hello-world:latest"
],
"SharedSize": -1
}
]
2.查看容器:
先运行一个nginx容器:docker run --name mynginx -p 80:80 -d nginx
docker-cli方式:
1
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
919b34a22018 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp mynginx请求Docker Daemon:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50[vagrant@docker-host ~]$ curl -s --unix-socket /var/run/docker.sock http:/containers/json | jq .
[
{
"Mounts": [],
"NetworkSettings": {
"Networks": {
"bridge": {
"DriverOpts": null,
"MacAddress": "02:42:ac:11:00:02",
"GlobalIPv6PrefixLen": 0,
"GlobalIPv6Address": "",
"IPv6Gateway": "",
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "89d9f74c2884582696971298095e85c9c7df332a356c4b3a4dc09807eb6d457f",
"EndpointID": "53d712df1ad9bd9093b8492c1abace5fe72785cd80189aa4c64d7652dff38490",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16
}
}
},
"HostConfig": {
"NetworkMode": "default"
},
"Status": "Up 11 minutes",
"State": "running",
"Id": "919b34a2201822a04fb1160c1c2369580d7b9ef9e7f1e9c77ad4da8761649fb9",
"Names": [
"/mynginx"
],
"Image": "nginx",
"ImageID": "sha256:f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35",
"Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
"Created": 1603879410,
"Ports": [
{
"Type": "tcp",
"PublicPort": 80,
"PrivatePort": 80,
"IP": "0.0.0.0"
}
],
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
}
}
]
如果去看看 Engine API,你会发现其它的请求也都是用类似方式发送的,更多API可以参考官方文档,目前最新的版本是v1.40:https://docs.docker.com/engine/api/v1.40/
至此,我们对docker的client、server架构有了清楚的认识:Docker Daemon相当于一个server,监听来自/var/run/docker.sock的请求,然后做出各种响应,例如返回镜像列表,创建容器。
更多精彩内容:mrxccc