本文阐述如何通过SSH协议与Docker Daemon通信。
Docker客户端通常通过Unix套接字在本地与守护程序通信 /var/run/docker.sock
,或通过网络通过TCP套接字。 以下是启动时提供给Docker守护程序的选项的典型示例:
# ssh root@123.57.79.224
Last login: Mon Mar 23 00:35:48 2020 from 111.199.154.70
Welcome to Qiniu Cloud Elastic Compute Service !
[root@iZ2zebzqqnls3u8zisdw00Z ~]# ps -ef |grep dockerd
root 23438 1 0 00:41 ? 00:00:03 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root 24354 24336 0 08:15 pts/0 00:00:00 grep --color=auto dockerd
Docker的客户端和服务端通信有三种方式
-H unix://
指的是Docker使用本地的unix套接字/var/run/docker.sock
进行通信-H tcp://0.0.0.0:2376
使守护程序可以通过端口2376上的任何网络接口使用。需要在安全组中打开此端口(并且,如果可能的话,请将该端口限制为IP地址白名单),以便远程客户端可以访问守护程序,为了安全起见,一般不建议开启。-H fd://
这是在systemd内部运行Docker是使用的远程通信方式,由systemd创建套接字并激活Docker守护进程。
如何通过ssh协议远程操作Docker服务
由于SSH被广泛使用,并且通常是默认情况下允许的协议之一,因此直接通过SSH访问Docker守护程序可能很方便。Docker 18.09使这成为可能,下面进行一下。
- 准备一个安装好版本在18.09或者更新的Docker服务
curl -s https://get.docker.com | sh
systemctl enable --now docker.service
ps -ef |grep dockerd | egrep -v grep
root 23438 1 0 00:41 ? 00:00:06 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
- 然后创建一个私钥,用于无密访问远程主机
ssh-keygen -t rsa
- 使用Docker -H通过ssh协议操作远程主机上的Docker
docker -H ssh://root@123.57.79.224 run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
现在就有了4种远程访问Docker的方式了,但是前面三种你还记得如何使用的吗?
回顾如何通过tcp/fd/unix远程访问Docker
-H fd://如何使用
每次安装完Docker服务之后,在systemd文件中都会发现-H fd://
这究竟是什么意思呢?我们是否能通过fd://
的方式进行访问docker daemon,测试一下:
- 先停下Docker服务
systemctl stop docker
- 查看是否有Docker的进程
# ps aux | grep 'docker' | egrep -v grep
lsof -Ua | grep 'docker' | egrep -v grep
- 启动
docker.socket
# systemctl start docker.socket
# ps aux | grep 'docker' | egrep -v grep
# lsof -Ua | grep 'docker' | egrep -v grep
systemd 1 root 29u unix 0xffff88022d286800 0t0 118203 /var/run/docker.sock
启动之后docker.socket
,我们可以看到仍然没有docker进程在运行,但是套接字/var/run/docker.sock
已经创建,它属于该进程systemd
,实际上,套接字现在已经准备好接收请求,即使docker
尚未运行。systemd将docker.service
在第一个请求到来时启动,将已创建的套接字传递给Docker
- 开始
docker.service
# systemctl start docker.service
# ps aux | grep 'docker' | egrep -v grep
root 25748 3.3 0.8 580192 71484 ? Ssl 09:19 0:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Docker现在正在运行.
- 现在我们将docket.socket和docker.service停止掉,然后手动使用
fd://
启动docker
# systemctl stop docker.socket
# systemctl stop docker.service
# ps aux | grep 'docker' | egrep -v grep
# lsof -Ua | grep 'docker' | egrep -v grep
# /usr/bin/dockerd -H fd://
INFO[2020-03-23T09:21:21.010104928+08:00] Starting up
failed to load listeners: no sockets found via socket activation: make sure the service was started by systemd
当使用时-H fd://
,docker将期望套接字通过其父进程传递,而不是自己创建。由Systemd启动时, Systemd会执行此工作,但是在终端上手动启动时,您不会执行此工作,因此docker守护进程失败并中止。
-H tcp://ip:port如何使用
- 我们查看一下docker.service的位置,然后增加一个tcp访问方式
# diff /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.service.bak
14c14
< ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:8888 -H fd:// --containerd=/run/containerd/containerd.sock
.> ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
- 重启查看是否添加成功
systemctl daemon-reload
systemctl restart docker.service
# ps aux | grep 'docker' | egrep -v grep
root 26277 0.7 0.8 449120 69460 ? Ssl 09:29 0:00 /usr/bin/dockerd -H tcp://0.0.0.0:8888 -H fd:// --containerd=/run/containerd/containerd.sock
- 在添加成功之后,我们在通过tcp和fd的方式远程尝试一下:
# docker -H fd://192.168.0.230:8888 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker -H tcp://192.168.0.230:8888 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 所以你明白了吗?但是为了安全起见,不建议开启docker的tcp端口,或者对Docker远程访问开启证书安全访问,不然你会摊上事儿的。
- 然后我们在恢复一下现场。😆
-H unix:// 如何使用
- 首先准备一个nginx镜像
docker pull nginx
- 使用unix套接字创建一个nginx容器
# curl -XPOST --unix-socket /var/run/docker.sock -d '{"Image":"nginx"}' -H 'Content-Type: application/json' http://localhost/containers/create
{"Id":"c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de","Warnings":[]}
- 通过返回的容器ID,启动该容器
# curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de/start
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4a739ff6d6b nginx "nginx -g 'daemon of…" About a minute ago Up 13 seconds 80/tcp reverent_edison
- 我们也可以通过unix套接字监听Docker的事件:
# curl --unix-socket /var/run/docker.sock http://localhost/events
"status":"create","id":"c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de","from":"nginx","Type":"container","Action":"create","Actor":{"ID":"c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de","Attributes":{"image":"nginx","maintainer":"NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e","name":"reverent_edison"}},"scope":"local","time":1584924907,"timeNano":1584924907738224502}
{"Type":"network","Action":"connect","Actor":{"ID":"8ca197c838f66decc5fc79996f78021597d928a26c0d011984416a6c9616a315","Attributes":{"container":"c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de","name":"bridge","type":"bridge"}},"scope":"local","time":1584924984,"timeNano":1584924984914048199}
{"status":"start","id":"c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de","from":"nginx","Type":"container","Action":"start","Actor":{"ID":"c4a739ff6d6ba66e80be9a669aa9ce7cf0044b524e0606433e09810b4cc084de","Attributes":{"image":"nginx","maintainer":"NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e","name":"reverent_edison"}},"scope":"local","time":1584924985,"timeNano":1584924985130585919}
好了。万字长文书写到此,你学到了吗?