使用本地命令调用远程 Docker
我平时使用 M 系列处理器的 Mac 笔记本处理工作,偶尔会使用到 Docker 构建、调试一些镜像,次数不多,但是整个 Docker 应用会占掉磁盘几十 GB 的空间,且随着使用缓存的增加,还会越来越大。另一方面 ARM 架构的镜像无法兼容生产环境的 x86 服务器,如老旧的 MySQL5.7 就根本没有 ARM 架构的镜像,因此在考虑如何利用内网或外网中服务器的 Docker 服务处理这些工作,从而避免在本机安装 Docker 环境。
通过 SSH 直接进入到远端装有 Docker 的服务器是一个选择,但是远程连接的开发总是有很强的割裂感,尤其是各类现代编辑器的远程支持,都不如直接在本地的体验好。
K8s 集群的管理者通常在使用 kubectl 命令行工具操作的时候,可以直接在本地随意一台主机上查看所有集群的状态。Docker 官方其实也提供了类似的解决方案,就是开放 Docker 服务的端口,利用 socket 连接进行远程通信。
具体的结构是这样的:
这样无论在本地使用 docker ps
命令,还是 build
一个镜像,都是直接调用远程的 Docker 服务来进行任务,任何基于 Docker 的工具,比如 lazydocker、VSCode 的 Docker 插件等,都能成功连接到该远程服务器。
接下来说一下配置方法,想要参考官方说明的,可以看 这里 (注意,该方法不被官方推荐,原因下文会讲)。
服务端配置
编辑配置文件 /etc/docker/daemon.json
,在其加入以下内容:
{
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
重启 docker 服务,如果发现无法重启,看看是不是启动指令与配置文件有内容冲突。可以检查 /lib/systemd/system/docker.service
服务文件,找到启动的指令中是不是有 -H fd://
这么个参数,其中的 -H
可能会与配置中的 hosts 冲突,去掉即可,去掉后要记得使用 systemctl daemon-reload
重载一下服务,然后重启 docker。
客户端配置
客户端的 docker 命令,默认使用本地的 docker 服务进行通信,而修改默认 host 的方法是修改环境变量 DOCKER_HOST
,Linux/MacOS 系统可以直接修改 .zshrc
或是 .bashrc
这样的终端实现,在配置中添加以下内容:
export DOCKER_HOST=tcp://192.168.1.225:2375
其中 192.168.1.225
可以换成你自己的服务器 IP 地址。
经过以上配置,本地的 Docker cli 工具的命令就可以直接回显远程服务器的 docker 信息了,但是新的问题来了,这个过程并没有进行鉴权,如果服务器在公网,端口暴露后其他人岂不是可以直接操作服务器中的 Docker 服务了。
没错,所以以上方法仅限于在同一个内网中,且服务器的 2375 端口并未对外暴露的情况下使用,生产环境千万不可如此操作。
Docker 官方更推荐的方式是使用更为安全的 ssh 或是 https 协议进行远程调用。https 的配置方式略微复杂,需要的可以去读 官方文档 。这里只介绍 ssh 通道的方式,相比其他所有方案都更为简单。
更为简单安全的 SSH 配置方式
与 TCP 的配置方式相同,其实只需要将 DOCKER_HOST
设置为 ssh://用户@ip
即可,比如在 shell 配置中增加以下内容:
export DOCKER_HOST=ssh://root@192.168.1.225
要注意的是,该处配置的 ssh 并不支持用户密码的登录方式,因此要提前配置好 SSH 的密钥方式登录,否则将会被提示权限拒绝。同时,使用该方式无需在服务器端做任何 Docker 相关的配置修改,也就是说,如果前边配置了 TCP 的连接,要记得清空 /etc/docker/daemon.json
文件中关于 host 的配置,否则端口依然会被恶意访问。
那 SSH 更安全,为什么我还要介绍基于 tcp 端口的连接方式呢?原因有下:
- 我只是在内网中调试,测试服务器并未对外暴露,几乎不存在安全问题
- 基于 SSH 协议的通信毕竟进行了一次鉴权,反应速度明显没有直接 TCP 到 Docker 快
- 简要概述其远程通信的工作原理
对于第二条,官方也提供了对于速度的优化方案,就是在本地的 ~/.ssh/config
配置文件中添加以下内容,增加 SSH 的复用而减少每次 docker 命令都要重新建立连接的延迟:
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
如此则可以将 ssh 下使用 docker 的体验提升到接近 TCP 直连的方式。