docker - 如何从外部连接到虚拟机中容器内的 Web 应用程序?
问题描述
我有一个设置是:
PC > Fedora(Hyper-V VM) > 运行 Web 应用程序的容器
我面临的问题是我无法从我的 PC 连接到 Web 应用程序(PC > Container Web 应用程序)
当服务启动时,它显示它正在监听http://0.0.0.0:8000
[2021-05-27 22:29:57 +0000] [23] [INFO] Starting gunicorn 20.1.0
[2021-05-27 22:29:57 +0000] [23] [INFO] Listening at: http://0.0.0.0:8000 (23)
[2021-05-27 22:29:57 +0000] [23] [INFO] Using worker: sync
[2021-05-27 22:29:57 +0000] [25] [INFO] Booting worker with pid: 25
[2021-05-27 22:29:57 +0000] [26] [INFO] Booting worker with pid: 26
[2021-05-27 22:29:57 +0000] [27] [INFO] Booting worker with pid: 27
尝试连接到http://0.0.0.0:8000不起作用,而是使用容器 IP:8000 连接,例如:172.17.0.2:8000
在我的 VM 上执行此操作很好,我可以连接并使用该应用程序,但它在我的 PC 上不起作用。我也尝试使用 VM ip、0.0.0.0 和容器 IP 进行连接,就像在 VM 中一样。但是这些选项都不起作用。
我尝试使用 iptables 转发端口,但我不知道如何准确使用它。我尝试用谷歌搜索一些命令并使用它,但没有找到解决方案。
有什么帮助吗?也许这与我没有看到的另一件事有关
解决方案
这里有几个层,每个层都有自己的一组 IP 地址。
+------------------------+
| Host +---------------+ |
| | VM +--------+ | |
| | | Docker | | |
| | +--------+ | |
| +---------------+ |
+------------------------+
重要的细节是每一层只能看到更远的一层。如果你在网络上另一台机器的堆栈之外,你不能直接访问虚拟机的 IP 地址;如果您在主机上,则无法访问容器专用 IP 地址。
但是,如果您使用该docker run -p
选项或 Composeports:
选项,它将导致运行 Docker 守护程序的层打开一个转发到容器的网络侦听器。在此设置中,由于 Docker 作为 VM 运行,因此docker run -p
将端口从 VM 转发到容器。
例如,假设您在 VM 内启动容器,并带有一个-p 12345:80
选项。如果您从主机连接到端口 12345 上的虚拟机 IP 地址,则会转发到容器中的端口 80。
vm$ docker run -d -p 12345:80 my-image
host$ curl http://vm:12345
+---------------------------------------------------+
| Host +---------------------------+ |
| | VM +-----------+ | |
| | | Docker | | |
| | | | | |
| | docker run | ./app | | |
| http://vm:12345 --> | -p 12345:80 | -addr :80 | | |
| | +-----------+ | |
| +---------------------------+ |
+---------------------------------------------------+
Docker Desktop 中使用了相同的设置,尽管 VM 相当隐藏,但这就是容器专用 IP 地址在 MacOS 或 Windows 主机上不起作用的原因。同样,如果没有本机 Linux 主机上的 VM,您将无法从其他主机访问容器专用 IP。
由于您始终可以使用 Docker 外部的已发布端口或使用 Docker 内部的容器网络访问容器,因此您永远不需要使用docker inspect
来查找容器的 IP 地址。
推荐阅读
- javascript - 对象数组元素在推送时被修改
- c++ - c++ 为什么要将基类的引用传递给派生类的构造函数
- css - 如何为 Angular 组件设置背景图片?
- laravel - 我怎样才能在 laravel 中检索这个?
- javascript - tag-it.js 不增加字段名上的计数器
- c# - 如何在 System.Web.Http.Filters.ActionFilterAttribute 的方法之间传递线程安全数据?
- cucumber - 没有示例的黄瓜无法识别场景
- python - 具有 lxmxn 广播形状的高级整数索引
- spring - Tomcat 中 server.port 属性的奇怪行为
- websocket - 从与服务器位于同一 LAN 中的客户端调用 DNS 时出现 Websockets 错误(Signalr2 和核心)