我最近发现的另一种可能性是通过 SSH 隧道控制远程 Docker Unix 套接字(感谢 https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160 我了解这种方法的地方)。
先决条件
您可以通过 SSH 连接到目标机器。出于安全性和便利性考虑,首选无密码、基于密钥的访问,您可以学习如何设置它,例如这里:https://askubuntu.com/questions/46930/how-can-i-set-up-password-less-ssh-login
此外,一些消息来源提到通过 SSH 隧道转发 Unix 套接字只能从 OpenSSH v6.7 开始(运行 ssh -V 进行检查),不过我没有在旧版本上尝试过。
SSH 隧道
现在,在本地位置和远程机器上的 Docker Unix 套接字之间创建一个新的 SSH 隧道:
ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote
或者,也可以绑定到本地端口而不是文件位置。确保端口已为连接打开并且尚未使用。
ssh -nNT -L localhost:2377:/var/run/docker.sock user@someremote
重定向 Docker 客户端
让终端保持打开状态并打开第二个终端。在那里,让您的 Docker 客户端与新创建的隧道套接字而不是本地 Unix Docker 套接字通信。
如果您绑定到文件位置:
export DOCKER_HOST=unix://$(pwd)/docker.sock
如果您绑定到本地端口(上面使用的示例端口):
export DOCKER_HOST=localhost:2377
现在,运行一些 Docker 命令,例如 docker ps 或启动容器、拉取映像等。只要 SSH 隧道处于活动状态,一切都会在远程机器上发生。为了再次运行本地 Docker 命令:
- 在第一个终端点击
Ctrl+C 关闭隧道。
- 如果您绑定到文件位置:再次删除临时隧道套接字。否则您以后将无法再次打开同一个:
rm -f "$(pwd)"/docker.sock
- 让您的 Docker 客户端再次与您的本地 Unix 套接字通信(如果未设置,这是默认值):
unset DOCKER_HOST
这样做的好处是您省去了复制docker-compose.yml 文件和其他资源或在远程机器上设置环境变量的麻烦(这很困难)。
非交互式 SSH 隧道
如果您想在无法使用交互式终端的脚本上下文中使用它,可以使用SSH ControlMaster and ControlPath options 来open and close the SSH tunnel in the background:
# constants
TEMP_DIR="$(mktemp -d -t someprefix_XXXXXX)"
REMOTE_USER=some_user
REMOTE_HOST=some.host
control_socket="${TEMP_DIR}"/control.sock
local_temp_docker_socket="${TEMP_DIR}"/docker.sock
remote_docker_socket="/var/run/docker.sock"
# open the SSH tunnel in the background - this will not fork
# into the background before the tunnel is established and fail otherwise
ssh -f -n -M -N -T \
-o ExitOnForwardFailure=yes \
-S "${control_socket}" \
-L "${local_temp_docker_socket}":"${remote_docker_socket}" \
"${REMOTE_USER}"@"${REMOTE_HOST}"
# re-direct local Docker engine to the remote socket
export DOCKER_HOST="unix://${local_temp_docker_socket}"
# do some business on remote host
docker ps -a
# close the tunnel and clean up
ssh -S "${control_socket}" -O exit "${REMOTE_HOST}"
rm -f "${local_temp_docker_socket}" "${control_socket}"
unset DOCKER_HOST
# do business on localhost again