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

zqdjd7g9  于 2023-01-25  发布在  Linux
关注(0)|答案(7)|浏览(321)

我的主机上有一个守护进程运行在某个端口(即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
4dbbbstv

4dbbbstv1#

我不确定你是否可以用docker的设置来做到这一点。如果我的理解是正确的,暴露端口不是你要找的。相反,建立从容器到主机的ssh端口转发可能是答案。

0md85ypi

0md85ypi2#

您可以轻松地使用-p 127.0.0.1:8008:8008并将容器的端口8008转发到localhost的端口8008

docker run -it -p 127.0.0.1:8008:8008 <image name>
6ju8rftf

6ju8rftf3#

如果在本地计算机上执行此操作,则可以在启动容器(--network host)时简单地将网络类型指定为host,这将使主机与Docker容器共享网络。
例如:
启动容器:

docker run -it --rm --network host <container>

在主机上,运行:

python3 -m http.server 8822

现在从容器运行:

curl 127.0.0.1:8822

如果一切顺利,您将在主机终端上看到流量。

Serving HTTP on 0.0.0.0 port 8822 (http://0.0.0.0:8822/) ...
127.0.0.1 - - [24/Jan/2023 22:37:01] "GET / HTTP/1.1" 200 -
kninwzqo

kninwzqo4#

docker run -d --name <NAME OF YOUR CONTAINER> -p 8008:8008 <YOUR IMAGE>
这会将容器中的端口8008发布到主机上的8008

cpjpxq1n

cpjpxq1n5#

因此,您需要考虑的是Docker容器有自己的网络堆栈(除非您明确告诉它与--net=host共享主机的堆栈)这意味着端口需要在Docker容器内部和外部都公开(文件),容器上公开的端口需要显式绑定到主机端口(在docker run命令中使用-p xxxx:yyyy)或隐式(在您的Dockerfile中使用EXPOSE,在命令行中使用-P),就像这里说的那样。如果您的Dockerfile不包含EXPOSE 8008,或者您没有在docker run命令中指定--expose 8008,你的容器不能与外界对话,* 即使你在你的docker run命令中使用-p 8008:8008!*
因此,要使主机上的tcp/8008与容器上的tcp/8008链接,您需要在Dockerfile中使用EXPOSE 8008(然后docker build您的容器)或docker run command中的--expose 8008。此外,您需要使用-P来隐式地或使用-p 8008:8008来显式地将所公开的容器端口链接到主机端口。执行此操作的docker run命令示例如下所示:
docker run -it --expose 8008 -p 8008:8008 myContainer
记住在-p 8008:8008命令行选项中,此操作的顺序是-p HOST_PORT:CONTAINER_PORT是很方便的。别忘了,除非您在主机 * 上的iptables * 中解除了该端口的阻塞,否则您将无法从互联网上的另一台计算机SSH到您的container。我总是最终忘记这一点,浪费半个小时才想起我忘记了主机上那个特定的tcp端口的iptables -A INPUT ...。但是您应该能够在不使用iptables规则的情况下从您的主机通过SSH连接到容器,因为它对本地连接使用了回环。

qv7cva1a

qv7cva1a6#

TL;DR:您可以使用特殊的主机名host.docker.internal来代替localhost * 在容器内 * 的任何地方,您想要访问主机上的localhost

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

完整答案:主机运行的是MacOS还是Windows?Docker Desktop文档中隐藏的事实是,MacOS上没有docker 0桥,Windows上也没有docker 0桥。显然这就是原因。在这两种情况下,解决方法都是(紧接在,在标题为“使用案例和解决方法”的子章节中)是使用特殊主机名host.docker.internal来代替要在主机上访问localhost的容器内的任何位置的localhost
如果主机是Linux,则有some Linux-only techniques for achieving this。但是,* host.docker.internal也可用于Linux主机,但必须先启用它。* 请参阅TL的Linux部分;DR,见上文,以获取说明。
通过这种方法,在OP的情况下,应该使用host.docker.internal:8008而不是localhost:8008。注意,这是在容器 * 内运行的应用程序代码的代码或配置更改 。没有必要在容器配置中提及端口。 不要尝试在docker run命令行中使用-p--expose *。不仅没有必要,但是如果您希望容器连接到的主机应用程序已经在侦听该端口,则容器将无法启动。

disbfnqx

disbfnqx7#

在检查了答案并做了一些调查后,我相信有两种方法可以做到这一点,这两种方法只适用于Linux环境。
第一个是在这篇文章How to access host port from docker container
第二个应该是当你docker rundocker container create时设置你的--network=host,在这种情况下,你的docker将使用你在Mac中使用的相同网络接口。
但是,上面两种方式都不能在Mac中使用,所以我认为在Mac环境中不能从容器转发到主机,如果我错了请纠正我。

相关问题