如何将容器上的localhost端口转发到主机上的localhost?

Set*_*ron 26 linux routing docker

我的主机上有一个守护进程在某个端口上运行(即8008),我的代码通常通过联系localhost:8008与守护进程交互.

我现在已经将我的代码容器化了,但还没有守护进程.如何将我的容器上的localhost:8008转发到运行容器的主机上的localhost:8008(以及守护进程).

以下是netstat -tlnp我的主人.我希望容器在主机上将localhost:2009转发到localhost:2009

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name            
tcp        0      0 127.0.0.1:2009          0.0.0.0:*               LISTEN      22547/ssh       
tcp6       0      0 :::22                   :::*                    LISTEN      -               
tcp6       0      0 ::1:2009                :::*                    LISTEN      22547/ssh            
Run Code Online (Sandbox Code Playgroud)

L0j*_*j1k 20

因此,您需要考虑的方法是Docker容器有自己的网络堆栈(除非您明确告诉它与主机的堆栈共享--net=host).这意味着当与主机端口链接时,端口需要在docker容器内部以及外部(文档)上暴露.容器上公开的端口需要显式绑定到主机端口(-p xxxx:yyyydocker run命令中)或隐式绑定(EXPOSE在Dockerfile中使用-P并在命令行中使用),如此处所示.如果您的Dockerfile不包含EXPOSE 8008,或者您没有--expose 8008docker run命令中指定,则您的容器无法与外界通信,即使您随后-p 8008:8008docker run命令中使用!

因此,要在容器上与tcp/8008链接的主机上获取tcp/8008,您需要EXPOSE 8008在Dockerfile(然后是docker build容器)内部或--expose 8008在您的容器中docker run command.此外,您需要-P隐式使用或-p 8008:8008明确地将该公开的容器端口链接到主机端口.docker run执行此操作的示例命令可能如下所示:

docker run -it --expose 8008 -p 8008:8008 myContainer

很容易记住,在-p 8008:8008命令行选项中,此操作的顺序是-p HOST_PORT:CONTAINER_PORT.此外,请不要忘记,除非您在主机上的 iptables中取消阻止此端口,否则您将无法从Internet上的其他计算机SSH连接到您的容器.我总是忘记这一点并浪费半小时才记得我忘记iptables -A INPUT ...了主机上那个特定的tcp端口.但是你应该能够在没有iptables规则的情况下从你的主机SSH到容器,因为它使用环回来进行本地连接.祝好运!

  • 如果容器的进程绑定到localhost:8008,这个答案不起作用,我解释了原始问题. (4认同)
  • 如果你的容器的进程被告知只监听localhost连接,绝对*没有*将能够与你的容器通信(除非我相信你在我的`docker run`命令中使用`--net = host`回答,它与您的容器共享主机的网络堆栈).Docker的网络将容器进程视为存在于他们自己的整个世界中.如果您告诉您的进程绑定到`localhost:8008`,例如在您的Golang Web应用程序中,您需要将其更改为"0.0.0.0:8008",以便确实能够与之通信. (2认同)

bos*_*oni 20

TL;DR:您可以使用特殊的主机名,host.docker.internal而不是要在主机上访问的容器内的localhost任何位置。注意:localhost

  • macOS 和 Windows 版本的 Docker Desktop 默认启用此功能。
  • Linux 主机(使用 Docker v 20.10 及更高版本 - 自 2020 年 12 月 14 日起)要求您添加--add-host=host.docker.internal:host-gateway到 Docker 命令以启用该功能。
  • Linux 上的 Docker Compose 要求您将以下行添加到容器定义中:
extra_hosts:
- "host.docker.internal:host-gateway"
Run Code Online (Sandbox Code Playgroud)

完整答案:主机运行的是 MacOS 还是 Windows?Docker Desktop 的文档中隐藏的事实是,MacOS 上没有 docker0 桥Windows 上也没有 docker0 桥。显然这就是造成这一情况的原因。在这两种情况下,解决方法(在标题为“用例和解决方法”的小节中给出)是使用特殊的主机名host.docker.internal来代替localhost您想要localhost在主机上访问的容器内的任何位置。

如果主机是 Linux,则有一些仅适用于 Linux 的技术可以实现此目的。不过,host.docker.internal也可以在 Linux 主机上使用,但必须先启用它。有关说明,请参阅上面 TL;DR 的 Linux 部分。

通过这种方法,在 OP 的情况下host.docker.internal:8008应该使用而不是localhost:8008. 请注意,这是容器内运行的应用程序代码的代码或配置更改。容器配置中无需提及端口。不要尝试在命令行中使用-p--exposedocker run。不仅没有必要,而且如果您希望容器连接的主机应用程序已经在侦听该端口,您的容器将无法启动。


Ste*_*enR 5

在检查了答案并做了一些调查之后,我相信有两种方法可以做到这一点,而这两种方法仅适用于 Linux 环境。

第一个是这篇文章如何从 docker 容器访问主机端口

--network=host当您docker run或 时,第二个应该设置为您的docker container create。在这种情况下,您的 docker 将使用您在 Mac 中使用的相同网络接口。

不过以上两种方式在Mac下都无法使用,所以我认为在Mac环境下无法从容器转发到主机。如果我错了请纠正我。


小智 -6

docker run -d --name <NAME OF YOUR CONTAINER> -p 8008:8008 <YOUR IMAGE>

8008这会将容器中的端口发布到8008主机上。

  • 说地址已被使用?我希望容器上的 localhost:8008 转发到主机上的 localhost:8008 (2认同)