如何从 Docker 容器内部访问在 WSL2 上运行的服务?

Posted

技术标签:

【中文标题】如何从 Docker 容器内部访问在 WSL2 上运行的服务?【英文标题】:How can I access a service running on WSL2 from inside a Docker container? 【发布时间】:2021-01-02 00:13:21 【问题描述】:

我正在使用 Windows 10 1909 并已安装 WSL2,使用 Ubuntu 20.04,19.03.13-beta2 docker 版本,已使用 WSL2 选项安装 Docker for Windows Edge 版本。集成效果很好,但我有一个问题无法解决。

在 WSL2 实例上,有服务正在运行,暴露了一些端口(3000、3001、3002,...)。从一个 docker 容器中,我需要访问特定开发场景(API 网关)的服务,而我无法开始工作。

我曾尝试直接使用 WSL2 IP 地址,但连接超时。我也尝试过使用host.docker.internal,它解析为 WSL2 IP 地址以外的其他东西,但它仍然不起作用。

有什么特殊的技巧我需要拉,还是这种路由目前不支持,但会支持,或者由于其他原因不可能?

这说明了我想要实现的目标:

其他路由工作 - 即我可以从 Windows 浏览器访问来自 WSL2 中的 node.js 进程的所有服务端口,并且我可以从 WSL2 内部和 Windows 中的容器访问公开的服务端口。只是这个缺失的链接我无法工作。

【问题讨论】:

我发誓我没有改变任何东西,但今天它起作用了! 我也发誓我没有改变任何东西,这在过去对我有用,但今天它不再有效......(如果我弄清楚我会报告什么做了...) @donmartin 你找到解决方案了吗? 不,是的。它在大多数情况下都有效。没有任何变化。 【参考方案1】:

那么你需要在windows机器上做的端口转发你在WSL机器上运行的端口,这个脚本端口转发4000端口

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"

在容器上你必须添加 docker run 命令

--add-host=host.docker.internal:host-gateway

或者如果您使用的是 docker-compose:

    extra_hosts:
      - "host.docker.internal:host-gateway"

然后在容器内你应该可以卷曲到

curl host.docker.internal:4000

并得到回应!

【讨论】:

【参考方案2】:

值得一提的是:如果您使用 WSL2 子系统 IP 地址,此场景有效。

如果您使用host.docker.internal,它确实不起作用 - 此 DNS 别名是在容器中定义的,但它映射到 Windows 主机的 IP 地址,而不是 WSL2 主机的 IP 地址,并且路由回 WSL2 主机内部不起作用。

这个(可能是暂时的)不起作用的原因有点不清楚 - 如果问题再次出现,我将重新审视这个答案,并且我设法找出实际问题可能是什么。

【讨论】:

我在我的应用程序中使用host.docker.internal,但我不通过docker run --add-host=host.docker.internal:host-gateway ... 启动容器如果我这样做,我无法从容器内部连接到外部。只需通过docker run -p 8080:8080 <etc> 启动容器

以上是关于如何从 Docker 容器内部访问在 WSL2 上运行的服务?的主要内容,如果未能解决你的问题,请参考以下文章

使用 WSL2 在 Docker Desktop 上运行的容器没有实时输出

无法从 docker 容器内部访问 datadog 代理

如何访问 Docker 桌面使用的 wsl2?

如何在docker上远程访问mariadb?

wsl2上的docker非常慢

无法连接到WSL2上的Landoop Docker容器