无法从 WSL2 docker 容器连接到 WSL2 localhost 服务器

Dan*_*cák 9 docker windows-subsystem-for-linux

我在 WSL2上的https://0.0.0.0:4000(也可以作为https://local.phx-cd.shoepping.at:4000访问,映射到 Ubuntu 主机文件中的 127.0.0.1)上运行一个简单的 Web 服务器乌班图。我可以从 Ubuntu 和 Windows 主机连接到它 - 到目前为止一切顺利。但此外,在我的 Docker for Win 与 WSL2 集成中,我运行了一个 selenium chrome 容器,该容器正在该 Web 服务器上连接和测试内容(使用网桥),但它无法连接到它!

我连接到容器并尝试卷曲到 Web 服务器 - 连接被拒绝。由于我的计算机上有双启动,我尝试切换到我的 Linux 发行版,在那里运行 Web 服务器并在 Linux Docker 中运行 selenium,并且与本地 Web 服务器的连接工作正常。所以我认为这与 WSL2 有关系。

我的 docker-compose.yaml(我省略了 selenium hub 配置)

selenium-chrome-local:
      image: selenium/node-chrome-debug:3.141.59
      restart: always
      ports:
        - 5901-5902:5900
      volumes:
        - /dev/shm:/dev/shm
        - ../../temp:/home/seluser/Downloads
      depends_on:
        - selenium-hub-local
      environment:
        - SCREEN_WIDTH=1920
        - SCREEN_HEIGHT=1080
      extra_hosts:
        - "local.phx-cd.shoepping.at:10.99.99.1"
      networks:
        - selgrid
        - dockerhost

 networks:
    selgrid:
    dockerhost:
      driver: bridge
      ipam:
        config:
          - subnet: 10.99.99.0/24
Run Code Online (Sandbox Code Playgroud)

如果您需要更多配置,请告诉我。谢谢。

Not*_*1ds 7

您确定 Ubuntu WSL2 实例正在桥接运行吗?默认情况下,WSL2 实例运行 NAT'd(而 WSL1 实例运行桥接)。因此,虽然 Docker 网络是桥接的,但如果没有一些额外的工作,它仍然无法访问经过 NAT 处理的 WSL2 VM。

我很确定您遇到了WSL 问题 #4150 中描述的根本问题。如果是这样,这里有一些事情可以尝试......

选项 #1 - 端口转发到 WSL2 实例

该 Github 问题中建议了几种解决方法,但适用于您的案例的基础知识归结为将端口 4000 从 Windows 主机接口转发到 WSL2 实例的私有 IP 地址。在 PowerShell 中:

netsh interface portproxy delete v4tov4 listenport="4000" # Delete any existing port 4000 forwarding
$wslIp=(wsl -d Ubuntu -e sh -c "ip addr show eth0 | grep 'inet\b' | awk '{print `$2}' | cut -d/ -f1") # Get the private IP of the WSL2 instance
netsh interface portproxy add v4tov4 listenport="4000" connectaddress="$wslIp" connectport="4000"
Run Code Online (Sandbox Code Playgroud)

请注意,您需要在每次重新启动后执行此操作,或者设置一个在登录时运行的脚本,如 Github 问题中所述(请参阅此评论)。

选项#2 - WSL1

我还建议,假设它适合您的工作流程并且您的 Web 应用程序在其上运行,您可以简单地使用 WSL1 而不是 WSL2。您可以通过以下方式尝试:

  1. 备份您现有的发行版(从 PowerShell 或 cmd,使用 wsl --export <DistroName> <FileName>
  2. 将备份导入到新的 WSL1 实例中 wsl --import <NewDistroName> <InstallLocation> <FileNameOfBackup> --version 1

简单地更改版本是可能的,但我倾向于在做之前有一个备份,只要你在备份,你最好把原始版本留在原地。

可能的选项 #3 -socat转发或隧道

虽然我没有直接测试您的特定用例,但我已经socat成功地在 WSL2 中进行了测试。从外观socat上看,它可以用于从 WSL2 到(至少)Windows 主机(Docker 容器可以访问该主机)的端口转发。有关与您的用例类似的用例,请参阅Github 上的此评论和示例。

可能的选项 #4 - WSL2 处于桥接模式

上面引用的 Github 线程也有一些关于如何使用 Hyper-V 在 WSL2 接口上启用桥接模式的详细信息。我相信这需要 Windows 10 Professional 或 Enterprise。它也必须在每次重新启动后完成,就像选项 1 一样。同样,如果端口转发或 WSL1 可以完成您需要的操作,那么在这种情况下可能有点过头了。

  • [答案](/sf/answers/3150209751/) 中描述的“host.docker.internal”是否可以解决这个问题? (2认同)
  • 好吧,这实际上与端口转发一起工作 - 当我卷曲 https://host.docker.internal:4000 时,我从本地服务器得到响应。但是,由于域名 local.phx-cd.shoeping.at 连接到受信任的证书,我希望能够使用它而不是 docker 内部。我看到 /etc/hosts 中生成了 `host.docker.internal` 条目,因此实现此功能的一种方法是在 Ubuntu 的启动上运行一个脚本来检索 docker 内部 IP,并在其中输入我的服务器的域名和该 IP。或者,还有更好的方法? (2认同)

tle*_*jmi 6

以管理员身份在 PowerShell 上运行以下命令:

替换{#requiredWindowsPort}为浏览器中将使用的端口

替换{#requiredWSL2Port}为您要连接的 WSL2 中运行的端口。

netsh interface portproxy add v4tov4 listenport={#requiredWindowsPort}
listenaddress=0.0.0.0 connectport={#requiredWSL2Port}
connectaddress=$($(wsl hostname -I).Trim());
Run Code Online (Sandbox Code Playgroud)