到 Docker 容器的 SSH 隧道

Rya*_*son 5 port-forwarding ssh-tunnel docker

目标:本地连接到远程repl(例如通过lein repl :connect)。

在本地,这很容易:

  1. 运行服务器(它在端口 8081 上启动嵌入式 nrepl 服务器)
  2. 跑吧lein repl :connect 8081,瞧!复制已连接

当 repl 在未打开的端口上运行时,我还通过使用 SSH 隧道连接到远程服务器上的 repl:

  1. 在 some.host 上,运行服务器(它在端口 8081 上启动嵌入式 nrepl 服务器)
  2. SSH隧道ssh -N -T -L 8081:localhost:8081 me@some.host
  3. 在本地,lein repl :connect 8081瞧!复制已连接

但是,我当前的设置是“服务器”在 Docker 容器中运行,该容器映射端口 8081。因此,为了连接到 nrepl 服务器,必须转到 local -> some.host -> docker-container -> nrepl 。

我可以看到我的 docker 容器映射了端口 8081:

$ sudo docker port container-id 8081
0.0.0.0:8081
Run Code Online (Sandbox Code Playgroud)

并且,在托管 docker 容器的服务器上,我可以看到端口 8081 正在侦听:

$ netstat -anl | sed -n '2p;/8081/p'
Proto    Recv-Q    Send-Q    Local Address   Foreign Address     State  
tcp      0         0         :::8081         :::*                LISTEN
Run Code Online (Sandbox Code Playgroud)

看起来我可以为端口 8081 打开 SSH 隧道;例如,运行时没有错误/警告:

ssh -N -T -L *:8081:localhost:8081 me@some.host
Run Code Online (Sandbox Code Playgroud)

这让我认为我拥有正确的 SSH 隧道,但每当我尝试连接到正在运行的 repl 服务器时,它都会立即失败,如下所示:

$ lein repl :connect 8081
Connecting to nREPL at 127.0.0.1:8081
SocketException The transport's socket appears to have lost its connection to the nREPL server
Run Code Online (Sandbox Code Playgroud)

值得注意的是,错误是连接丢失,因为在未打开SSH 隧道的情况下运行,相同的命令会失败并显示Connection refused. 这让我认为 SSH 隧道没问题,问题出在转发到 docker 容器的服务器上,这就是为什么这个标题是一个关于从client -> server -> docker container.

我认为这可能与 SSH GatewayPorts 有关,因此我尝试启用 GatewayPorts,但这并没有改变任何东西。

问题:

  1. 上面的 SSH 隧道方法有什么明显的错误吗?
  2. 如何确定连接在何处被断开?
  3. 还有其他建议吗?

谢谢!

Rya*_*son 3

而且……事实证明隧道没有任何问题。

问题是在 docker 容器内启动嵌入式 nrepl 服务器需要显式绑定到“0.0.0.0”。如果没有这个,nrepl 服务器默认绑定到“localhost”,这使得它无法从 docker 容器外部访问,尽管有端口映射,因为 docker 端口映射使用 0.0.0.0:。一旦 nrepl 服务器正确绑定,端口映射就会处理剩下的事情。