从Docker零基础到懂一点实践教程(五)

Docker客户端和守护进程

Docker的CS模式

在Docker的实现机制中,有两个重要的概念,“Docker客户端”和“Docker守护进程”。“Docker守护进程”运行在宿主计算机上,在CS模式中充当Server的角色,它为“Docker客户端”提供服务,并且完成Docker中的各项任务。

sequenceDiagram
用户->>Docker客户端: 命令行指令
Docker客户端->>Docker守护进程: 执行指令
Docker守护进程->>Docker客户端: 执行结果
Docker客户端->>用户: 命令行输出

除了“Docker客户端”这个最主要的与“Docker守护进程”交互的方式外,Docker还提供了RESTful风格的“Remote API”,这就意味着我们可以通过编写程序,调用这些API来将自己的程序与Docker进行集成。“Remote API”在某些复杂的情况下,也支持“STDIN”、“STDOUT”以及“STRERR”的通讯机制进行交互。

sequenceDiagram
用户->>自定义程序: 程序输入
自定义程序->>Docker守护进程: Remote API
Docker守护进程->>自定义程序: 执行结果
自定义程序->>用户: 程序输出

Docker Remote API Reference:
https://docs.docker.com/engine/reference/api/docker_remote_api/

连接方式

“Docker客户端”和“Docker守护进程”是通过socket进行连接的,官方提供了三种进行连接的模式:
- unix:///var/run/docker.sock
- tcp://host:port
- fd://socketfd

其中,“unix”模式是默认提供的,我们来验证一下:

schen@scvmu01:~$ ps -ef | grep docker
root      1106     1  0 21:14 ?        00:00:04 /usr/bin/dockerd -H fd://
root      1224  1106  0 21:15 ?        00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc
schen     1603  1582  0 22:03 pts/0    00:00:00 grep --color=auto docker
schen@scvmu01:~$ 
schen@scvmu01:~$ docker version
Client:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 05:33:38 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 05:33:38 2016
 OS/Arch:      linux/amd64
schen@scvmu01:~$ 
schen@scvmu01:~$ ls -l /var/run/docker.sock 
srw-rw---- 1 root docker 0 Sep  7 21:14 /var/run/docker.sock
schen@scvmu01:~$ 
schen@scvmu01:~$ nc -U /var/run/docker.sock
GET /info HTTP/1.0

HTTP/1.0 200 OK
Content-Type: application/json
Server: Docker/1.12.1 (linux)
Date: Thu, 17 Nov 2016 12:16:25 GMT
Content-Length: 1874

{"ID":"VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL","Containers":26,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":26,"Images":44,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","83"],["Dirperm1 Supported","true"]],"SystemStatus":null,"Plugins":{"Volume":["local"],"Network":["host","bridge","null","overlay"],"Authorization":null},"MemoryLimit":true,"SwapLimit":false,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":false,"NFd":14,"OomKillDisable":true,"NGoroutines":22,"SystemTime":"2016-11-17T20:16:25.663603424+08:00","ExecutionDriver":"","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-45-generic","OperatingSystem":"Ubuntu 16.04 LTS","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":1,"MemTotal":512176128,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"scvmu01.shichen.org","Labels":null,"ExperimentalBuild":false,"ServerVersion":"1.12.1","ClusterStore":"","ClusterAdvertise":"","SecurityOptions":["apparmor","seccomp"],"Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null,"Nodes":0,"Managers":0,"Cluster":{"ID":"","Version":{},"CreatedAt":"0001-01-01T00:00:00Z","UpdatedAt":"0001-01-01T00:00:00Z","Spec":{"Orchestration":{},"Raft":{},"Dispatcher":{},"CAConfig":{},"TaskDefaults":{}}}},"LiveRestoreEnabled":false}
schen@scvmu01:~$ 

可以看到,在Docker的守护进程dockerd的参数列表中,我们并没有指定“unix”套接字,但是我们却可以通过它来访问Docker的守护进程,并使用HTTP协议获取有关Docker守护进程的信息,当然这些信息是以JSON格式提供的。

Docker守护进程的配置和操作

查看Docker守护进程的运行状态

要查看Docker守护进程的状态,我们可以使用Linux自带的ps命令:

schen@scvmu01:~$ ps -ef | grep docker
root      1106     1  0 21:14 ?        00:00:04 /usr/bin/dockerd -H fd://
root      1224  1106  0 21:15 ?        00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc
schen     1603  1582  0 22:03 pts/0    00:00:00 grep --color=auto docker
schen@scvmu01:~$ 

除了我们熟悉的ps命令外,我们还可以通过status命令进行查看,但是由于该命令在Ubuntu虚拟机中需要额外的设置才能使用,故这里不再演示。而如果status命令不存在,可以使用sudo apt-get install upstart进行安装。

启动、停止、重启Docker守护进程

我们可以使Linux的service命令来管理Docker的守护进程,它可以:
1. 启动docker的守护进程 sudo service docker start
2. 停止docker的守护进程 sudo service docker stop
3. 重启docker的守护进程 sudo service docker restart
4. 查看docker的守护进程 sudo service docker status

schen@scvmu01:~$ sudo service docker status | grep PID
 Main PID: 1080 (dockerd)
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker stop
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker status | grep PID
 Main PID: 1080 (code=exited, status=0/SUCCESS)
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker start
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker status | grep PID
 Main PID: 27822 (dockerd)
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker restart
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker status | grep PID
 Main PID: 27937 (dockerd)
schen@scvmu01:~$ 

Docker守护进程的启动选项

Docker守护进程提供了非常丰富的配置选项,其中包括:
1. 守护进程运行相关选项(-D, -e, -g, --icc, -l, --label, -p等)
2. Docker服务器连接相关选项(-G, -H, --tls, --tlscacert, --tlscert, --tlskey, --tlsverify等)
3. RemoteAPI相关选项(--api-enable-cors等)
4. 存储相关选项(-s, --selinux-enabled, --storage-opt等)
5. Registry相关选项(--insecure-registry, --registry-mirror等)
6. 网络相关选项(-b, --bip, --fixed-cidr, --dns, --dns-search, --ip, --ip-forward, --ip-masq, --iptables, --ipv6, --mtu等)

有关于这些参数的解释,可以通过docker daemon --help命令查看,也可以查阅Docker的官方网站。

Docker命令行参考:https://docs.docker.com/engine/reference/commandline/

修改Docker守护进程的启动配置

我们可以通过修改/etc/default/docker文件实现对Docker守护进程的启动配置。

schen@scvmu01:~$ sudo vi /etc/default/docker
schen@scvmu01:~$ 
schen@scvmu01:~$ grep "^DOCKER_OPTS" /etc/default/docker
DOCKER_OPTS="--label name=docker_server_1"
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker restart
schen@scvmu01:~$ 
schen@scvmu01:~$ ps -ef | grep docker
root     28238     1 13 22:39 ?        00:00:01 /usr/bin/dockerd -H fd://
root     28244 28238  0 22:39 ?        00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc
schen    28333 27696  0 22:39 pts/0    00:00:00 grep --color=auto docker
schen@scvmu01:~$ 

这时我们发现设置并没有生效,这是因为/etc/default/docker文件是为upstartSysVInit准备的(正如文件第一行注释所言),而使用service命令时并不会读取它,因此我们还需要做如下更改:

schen@scvmu01:~$ sudo mkdir -p /etc/systemd/system/docker.service.d
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo vi /etc/systemd/system/docker.service.d/Using_Environment_File.conf
[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// $DOCKER_OPTS
~
~
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo systemctl daemon-reload
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker restart
schen@scvmu01:~$ 
schen@scvmu01:~$ ps -ef | grep docker
root      4287     1  0 21:52 ?        00:00:02 dockerd -H fd:// --label name=docker_server_1
root      4296  4287  0 21:52 ?        00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shim docker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc
schen     4395  2377  0 22:07 pts/1    00:00:00 grep --color=auto docker
schen@scvmu01:~$ 

有关此问题的参考文献:
- https://github.com/docker/docker/issues/9889
- http://docs.master.dockerproject.org/engine/admin/systemd/

Docker客户端与守护进程

通过配置Docker守护进程,可以使Docker客户端和守护进程运行在不同的服务器上,即实现Docker的远程访问。

环境准备

准备工作:
1. 第二台安装有Docker的服务器;
2. 修改Docker守护进程启动选项,用--label区别服务器;
3. 保证Client API与Server API版本一致;

我们在第一台服务器上将其Docker守护进程的label指定为name=docker_server_1,同样将第二台服务器上的label指定为name=docker_server_2,并重启Docker服务。以下是这两台Docker服务器的详细信息:

schen@scvmu01:~$ docker info
Containers: 15
 Running: 0
 Paused: 0
 Stopped: 15
Images: 8
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 49
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-45-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.4 MiB
Name: scvmu01.shichen.org
ID: VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: shichen
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 name=docker_server_1
Insecure Registries:
 127.0.0.0/8
schen@scvmu01:~$ 
schen@scvmu02:~$ docker info
Containers: 15
 Running: 0
 Paused: 0
 Stopped: 15
Images: 8
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 49
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: overlay null host bridge
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-45-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.4 MiB
Name: scvmu02.shichen.org
ID: VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: shichen
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 name=docker_server_2
Insecure Registries:
 127.0.0.0/8
schen@scvmu02:~$ 

修改服务器端配置

要实现远程访问,我们就要修改docker守护进程启动选项-H的值,将它指定为tcp模式。

schen@scvmu01:~$ sudo vi /etc/default/docker
schen@scvmu01:~$ 
schen@scvmu01:~$ grep "^DOCKER_OPTS" /etc/default/docker
DOCKER_OPTS="--label name=docker_server_1 -H tcp://0.0.0.0:2375"
schen@scvmu01:~$ 
schen@scvmu01:~$ sudo service docker restart
schen@scvmu01:~$ 

我们在第一台服务器上,将Docker守护进程-H选项指定为tcp://0.0.0.0:2375,这里使用全零的地址是让Docker绑定服务器自身的IP地址,而“2375”是Docker服务器常用的端口号。现在我们来到第二台服务器上,验证一下我们的配置:

schen@scvmu02:~$ curl http://scvmu01:2375/info
{"ID":"VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL","Containers":15,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":15,"Images":8,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","49"],["Dirperm1 Supported","true"]],"SystemStatus":null,"Plugins":{"Volume":["local"],"Network":["overlay","null","host","bridge"],"Authorization":null},"MemoryLimit":true,"SwapLimit":false,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":false,"NFd":15,"OomKillDisable":true,"NGoroutines":23,"SystemTime":"2016-10-25T19:50:46.471062364+08:00","ExecutionDriver":"","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-45-generic","OperatingSystem":"Ubuntu 16.04 LTS","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":1,"MemTotal":512176128,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"scvmu01.shichen.org","Labels":["name=docker_server_1"],"ExperimentalBuild":false,"ServerVersion":"1.12.1","ClusterStore":"","ClusterAdvertise":"","SecurityOptions":["apparmor","seccomp"],"Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null,"Nodes":0,"Managers":0,"Cluster":{"ID":"","Version":{},"CreatedAt":"0001-01-01T00:00:00Z","UpdatedAt":"0001-01-01T00:00:00Z","Spec":{"Orchestration":{},"Raft":{},"Dispatcher":{},"CAConfig":{},"TaskDefaults":{}}}},"LiveRestoreEnabled":false}
schen@scvmu02:~$ 

因为主机名已经设置好,所以我们可以直接使用主机名scvmu01代替其IP地址。使用curl命令访问远程Docker服务器的/info接口,得到了JSON格式的数据反馈,说明服务器已经可以正常连接了。

修改客户端配置

与服务端类似,客户端也支持-H选项,我们可以通过指定这个选项,让客户端与指定的服务端相连:

schen@scvmu02:~$ docker -H tcp://scvmu01:2375 info
Containers: 15
 Running: 0
 Paused: 0
 Stopped: 15
Images: 8
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 49
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: overlay null host bridge
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-45-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.4 MiB
Name: scvmu01.shichen.org
ID: VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: shichen
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 name=docker_server_1
Insecure Registries:
 127.0.0.0/8
schen@scvmu02:~$ 

当我们要频繁操作一个远程Docker服务器时,重复地使用-H选项就会显得很麻烦,这时我们可以通过设定DOCKER_HOST环境变量解决这个问题:

schen@scvmu02:~$ export DOCKER_HOST="tcp://scvmu01:2375"
schen@scvmu02:~$ 
schen@scvmu02:~$ docker info
Containers: 15
 Running: 0
 Paused: 0
 Stopped: 15
Images: 8
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 49
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: host bridge null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-45-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.4 MiB
Name: scvmu01.shichen.org
ID: VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: shichen
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 name=docker_server_1
Insecure Registries:
 127.0.0.0/8
schen@scvmu02:~$ 

当我们使用完远程的Docker服务器后,想要连接本机的Docker服务端,只需要将DOCKER_HOST变量置空即可:

schen@scvmu02:~$ export DOCKER_HOST=""
schen@scvmu02:~$ 
schen@scvmu02:~$ docker info
Containers: 15
 Running: 0
 Paused: 0
 Stopped: 15
Images: 8
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 49
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: host null bridge overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-45-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.4 MiB
Name: scvmu02.shichen.org
ID: VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: shichen
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 name=docker_server_2
Insecure Registries:
 127.0.0.0/8
schen@scvmu02:~$ 

指定多种连接方式

当我们回到第一台服务器上,发现Docker客户端仍然可以在不指定-H参数的情况下,直接与本地的服务端相连。这是因为Docker守护进程在启动时,还默认指定了-H fd://参数,这也说明我们可以通过给Docker守护进程指定多个-H参数来为Docker客户端提供更多的连接方式:

schen@scvmu01:~$ echo $DOCKER_HOST
schen@scvmu01:~$ 
schen@scvmu01:~$ docker info
Containers: 15
 Running: 0
 Paused: 0
 Stopped: 15
Images: 8
Server Version: 1.12.1
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 49
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: overlay null host bridge
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: apparmor seccomp
Kernel Version: 4.4.0-45-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.4 MiB
Name: scvmu01.shichen.org
ID: VVPW:WOIW:TCPI:YDUG:J67N:5DHU:WSWW:RMMN:64FK:KNHO:NPPH:ATSL
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: shichen
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 name=docker_server_1
Insecure Registries:
 127.0.0.0/8
schen@scvmu01:~$ ps -ef | grep dockerd
root      1131     1  0 19:34 ?        00:00:06 dockerd -H fd:// --label name=docker_server_1 -H tcp://0.0.0.0:2375
schen     1637  1587  0 20:31 pts/0    00:00:00 grep --color=auto dockerd
schen@scvmu01:~$ 

你可能感兴趣的:(Docker)