【问题标题】:Creating an SSH tunnel to a port already bound by Docker为已被 Docker 绑定的端口创建 SSH 隧道
【发布时间】:2020-02-12 07:35:18
【问题描述】:

我想将流量从远程服务器上的 docker 容器转发到我的本地开发服务器。

基本上我有以下设置,

  1. 我在端口 3000 上有一个本地开发服务器。
  2. 我有一个远程服务器,它运行一个带有 nginx 的 Docker 容器,用于接收传入的 Web 流量(未显示传入的 Web 流量)。这部分已经开始工作了。
  3. 容器中的传入 Web 流量被转发到容器中的端口 7890。
  4. 我已使用-p 7890:7890 将容器上的端口 7890 发布到端口 7890 上的主机。
  5. 然后,我尝试使用ssh -R 7890:localhost:3000 -N myexampledomain.com 设置从远程服务器到本地网络服务器的反向ssh 隧道,但随后我收到消息Warning: remote port forwarding failed for listen port 7890,可能是因为Docker 已代表绑定了端口7890容器。

如何将流量从 Docker 容器转发到我的本地开发机器?

我觉得我在这里遗漏了部分谜题。你对如何解决这个问题有什么建议吗?出于各种原因,我想继续使用 Docker(我意识到将 Docker 扔出窗外会更容易实现这个特定示例)。

详细说明当前情况的图像(传入的网络流量除外)。

【问题讨论】:

  • 什么流量应该到达 nginx 容器,vs. 被路由到您的开发系统?我认为您的图表中令人困惑的一点是“容器发布”箭头指向另一个方向——它将流量从主机端口 7890 路由到 nginx 容器内的匹配端口。包括你的 nginx 配置片段和相关的docker run 命令可能有助于澄清事情。

标签: docker ssh tunneling


【解决方案1】:

您可以做的是在网络模式host下运行remote server(带有nginx的那个)中的docker容器。

这样,该容器将与主机位于同一网络中,主机将能够与您的远程端口转发创建的端口 7890 通信,而无需您进行任何端口映射,例如 -p 7890:7890

EDIT 1说清楚,而不是在远程主机上运行容器

docker run ... -p 7890:7890 ...

改为运行它

docker run ... --network host ...

EDIT 2 为了那些仍然对这个问题感到困惑的人的利益。我将在这里尝试详细说明:

他想达到什么目的

将来自远程服务器(暴露于 Internet)的所有请求转发到他的开发网络服务器。这样当来自互联网各地的用户访问远程服务器的 IP 时,请求将由运行在他的开发环境中的容器提供服务。

到目前为止他做了什么

  1. 创建侦听端口3000development webserver 容器。
  2. remote server 上创建nginx 容器,该容器侦听端口7890,并将该端口从容器映射到主机,因此主机也绑定到端口7890
  3. 从该容器中,创建一个从development webserverremote server 的远程ssh 端口转发,将remote server 中的端口7890 的所有流量转发到development webserver 正在侦听的端口3000

他面临的问题

step 3中,进行远程端口转发时,该命令会同时尝试绑定remote server中的7890端口,而step 2中已经在使用该端口

他问我们什么

任何解决此问题的建议,因为他仍想使用 Docker 解决方案。

我建议的解决方案

现在,有两个解决方案可以让他在这种情况下继续使用 Docker。

前 2 段中解释的第一个解决方案

这是最简单的,需要最少的修改。

  1. 由于使用 nginx 的想法是有一个反向代理,将来自 web 的流量从 1 个端口(例如 80)转发到另一个端口,即 7890 在这种情况下,nginx 容器只需要能够在 localhost 上发现由远程端口转发命令创建的7890 端口。
  2. 显然,将端口7890 从本地计算机映射到容器是行不通的,而且永远不是解决方案。这里可以做的是让nginx容器加入hostnetwork。这样,容器将能够看到主机绑定的所有端口,反之亦然。
  3. 如何做到这一点是在创建nginx 容器时运行docker run ... --network host ... 而不是docker run ... -p 7890:7890 ...
  4. 如果您使用的是 docker-compose,那么network_mode: "host" 是不错的选择。

第二种解决方案

这有点先进,但它确实可以完成工作。

  1. nginx 容器中安装ssh server,如official guide 中所述
  2. nginx 容器的端口22 映射到remote server 中的可用端口,例如30010。这样,从development webserver,你就可以通过remote server的端口30010直接ssh到nginx容器中。
  3. 像往常一样通过新的30010 端口创建一个 SSH 隧道,例如ssh -R 7890:localhost:3000 -N myexampledomain.com

【讨论】:

  • 这对于容器和 ssh 端口转发都试图在同一个主机端口上侦听的问题无济于事(事实上,不允许您重新映射,这会使问题变得更糟集装箱港口)。
  • 我的回答是:不要在远程主机上映射容器端口(因为它不起作用),而是在网络模式下运行它host!!!
  • docker run -p 7890:7890 选项暗示容器使用相同的端口号,所以这无济于事。最好尝试诊断实际问题,而不是建议禁用 Docker 的核心部分。
  • 是的,我的回答是不要使用-p 7890:7890,而是使用--network host。将进行编辑以使其清楚!
猜你喜欢
  • 1970-01-01
  • 2017-02-07
  • 2021-05-11
  • 2016-11-10
  • 2017-02-23
  • 1970-01-01
  • 2020-10-28
  • 2016-10-01
相关资源
最近更新 更多