簡體   English   中英

如何將容器上的本地主機端口轉發到主機上的本地主機?

[英]How can I forward localhost port on my container to localhost on my host?

我的主機上有一個守護進程在某個端口(即 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            

因此,您需要考慮的方式是 Docker 容器有自己的網絡堆棧(除非您明確告訴它與--net=host共享主機的堆棧)。 這意味着當與主機端口鏈接時,端口需要在 docker 容器內部和外部(文檔)公開。 容器上暴露的端口需要顯式綁定到主機端口(在 docker docker run命令中使用-p xxxx:yyyy )或隱式綁定(在EXPOSE中使用 EXPOSE 並在命令行中使用-P ),就像這里所說的. 如果您的 Dockerfile 不包含EXPOSE 8008 ,或者您沒有在 docker run 命令中指定--expose 8008 ,那么即使您在 docker docker run命令中docker run -p 8008:8008 ,您的容器也無法與外界通信

因此,要在與容器上的 tcp/8008 鏈接的主機上獲取 tcp/8008,您需要在EXPOSE 8008 (然后使用 docker docker build您的容器)或在 docker 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 另外,不要忘記您將無法從 Internet 上的另一台計算機通過 SSH 連接到您的容器,除非您在主機上的iptables 中也未阻止此端口。 我總是最終忘記了這一點並浪費了半個小時才想起我忘記了iptables -A INPUT ...用於主機上的特定 tcp 端口。 但是您應該能夠在沒有 iptables 規則的情況下從主機通過 SSH 連接到容器,因為它使用環回進行本地連接。 祝你好運!

TL;DR:您可以使用特殊的主機名host.docker.internal而不是localhost在容器內您想要訪問localhost上的 localhost 的任何地方。 注意:

  • macOS 和 Windows 版本的 Docker Desktop 默認啟用此功能。
  • Linux 主機(使用 Docker v 20.10 及更高版本 - 自 2020 年 12 月 14 日起)需要您在 Docker 命令中添加--add-host=host.docker.internal:host-gateway以啟用該功能。
  • Linux 上的 Docker Compose 要求您將以下幾行添加到容器定義中:
extra_hosts:
- "host.docker.internal:host-gateway"

完整答案:主機運行的是 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 請注意,這是在容器內運行的應用程序代碼的代碼或配置更改。 容器配置中無需提及端口。 不要嘗試在 docker docker run命令行中使用-p--expose 不僅沒有必要,而且如果您希望容器連接到的主機應用程序已經在偵聽該端口,您的容器將無法啟動。

在檢查了答案並進行了一些調查之后,我相信有兩種方法可以做到這一點,而這兩種方法只適用於 Linux 環境。

第一個是在這篇文章中如何從 docker 容器訪問主機端口

第二個應該設置你的--network=host當你 docker docker run或 docker docker container create 在這種情況下,您的 docker 將使用您在 Mac 中使用的相同網絡接口。

但是,以上兩種方式都不能在Mac中使用,所以我認為不可能從容器轉發到Mac環境中的主機。 如果我錯了,請糾正我。

我不確定您是否可以僅使用 docker 的設置來做到這一點。 如果我的理解是正確的,那么暴露端口不是你要找的。 相反,建立從容器到主機的 ssh 端口轉發可能是答案。

您可以輕松使用-p 127.0.0.1:8008:8008並將容器的端口8008轉發到本地主機的端口8008 一個示例 docker 命令是:

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

如果您在本地計算機上執行此操作,則可以在啟動容器時簡單地將 .network 類型指定為host ( -.network host ),這將使您的主機與 docker 容器共享 .network 。

例如:

啟動你的容器:

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 -

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

這會將容器中的端口8008發布到主機上的8008

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM