故障记录:VMware NAT 导致 Windows 后端无法访问虚拟机内 Docker 依赖服务
故障现象
在 Windows 本机启动项目时,前端 Vite 可以正常运行,但页面一发起接口请求就报错,常见表现包括:
- 前端终端出现
http proxy error - Vite 代理请求到
127.0.0.1:8000失败 - 报错内容为
ECONNREFUSED 127.0.0.1:8000 - 后端执行了
uvicorn启动命令,但服务没有真正对外可用
进一步查看后端日志,会发现应用卡在 Application startup 阶段,依次在 MySQL、MongoDB、Redis、RabbitMQ、Elasticsearch 等依赖初始化时失败。也就是说,表面症状是前端代理错误,实际症状是后端在启动阶段退出。
根因
根因不是前端代理配置错误,也不是单个数据库损坏,而是:
VMware 虚拟机使用 NAT 网络时,Windows 宿主机虽然可以 ping 通虚拟机地址
192.168.201.101,但无法稳定访问虚拟机内 Docker 暴露出来的 TCP 端口,导致后端在初始化 MySQL、MongoDB、Redis、RabbitMQ、Elasticsearch 等依赖时失败退出。
这个问题的关键点有三个:
ping通只说明网络层可达,不代表应用依赖的 TCP 端口可达。- 后端依赖都部署在同一台 Linux 虚拟机中,因此第一个报错的 MySQL 只是最先暴露的问题,不是唯一问题。
- NAT 模式下,宿主机访问虚拟机 Docker 暴露端口的路径不稳定,导致多依赖联调场景容易整体失败。
排查步骤
1. 先确认问题是不是前端代理本身
如果 Vite 已经成功监听 http://localhost:3000/,但请求 /api/... 时出现 ECONNREFUSED 127.0.0.1:8000,优先判断后端是否真正启动成功,而不是先修改前端代理配置。
2. 确认后端是不是"没启动",还是"启动失败退出"
观察后端日志,重点看是否出现以下模式:
uvicorn命令执行成功- 应用进入
Waiting for application startup - 依赖初始化过程中报错
- 没有出现
Application startup complete.
如果是这种情况,说明后端不是没执行,而是启动阶段被外部依赖打断了。
3. 不要只盯着第一个 MySQL 报错
如果日志先报 MySQL 连接失败,不要立刻断定问题只在 MySQL。因为在这类架构里,MySQL、MongoDB、Redis、RabbitMQ、Elasticsearch 都在同一台虚拟机中,最常见的情况是:整条宿主机到虚拟机的依赖访问链路都有问题。
4. 用端口测试验证,不要只看 ping
在 Windows 上执行:
powershell
Test-NetConnection 192.168.201.101 -Port 3306
如果结果类似:
PingSucceeded : TrueTcpTestSucceeded : False
那么就可以确认:虚拟机地址虽然可达,但 Docker 暴露出来的依赖端口不可达。这一步是定位根因的关键证据。
5. 检查 VMware 网络模式
最开始虚拟机使用的是 NAT 模式,如下图所示:

在这种模式下,虚拟机可以借宿主机上网,但宿主机访问虚拟机内 Docker 暴露的多个端口并不稳定,尤其容易在本地多依赖联调中出问题。
6. 临时验证:使用 SSH 端口转发判断服务本身是否正常
例如临时把本地端口转发到虚拟机 MySQL:
powershell
ssh -L 13306:127.0.0.1:3306 root@192.168.201.101
如果把后端配置改成 127.0.0.1:13306 后 MySQL 能通,说明:
- MySQL 容器本身是正常的
- 问题在宿主机到虚拟机的直连路径
这个方法适合验证,不适合长期使用,因为依赖太多时维护成本很高。
7. 把虚拟机改成桥接网络
长期修复方案是把 VMware 网卡改成 Bridged:

如果机器有 Wi-Fi 和有线网卡,自动桥接设置里只保留真实物理网卡,不要勾选 Wi-Fi Direct、Bluetooth 等虚拟或旁路适配器:

8. 刷新 Linux 网卡租约,确认桥接真正生效
桥接改完以后,CentOS 里的 ens33 可能仍保留原来的 NAT 地址 192.168.201.101,如下图:

此时需要执行:
bash
dhclient -r ens33
dhclient -v ens33
ip -4 addr show ens33
刷新后,虚拟机拿到了新的桥接地址 10.113.233.121:

9. 分层验证:容器、端口、连通性、应用
先在 Linux 中确认容器和端口:
bash
docker ps
ss -lntp | grep 3306
ss -lntp | grep 27017
ss -lntp | grep 6379
ss -lntp | grep 5672
ss -lntp | grep 9200
再在 Windows 中逐个确认端口可达:
powershell
Test-NetConnection 10.113.233.121 -Port 22
Test-NetConnection 10.113.233.121 -Port 3306
Test-NetConnection 10.113.233.121 -Port 27017
Test-NetConnection 10.113.233.121 -Port 6379
Test-NetConnection 10.113.233.121 -Port 5672
Test-NetConnection 10.113.233.121 -Port 9200
这一轮验证里还有一个插曲:MySQL 和 MongoDB 已经恢复,但 Redis 的 6379 仍然不通。最后确认是 Redis 容器没有运行,而不是桥接又失效了。这说明网络恢复以后,仍然要继续检查具体服务实例状态。
修复方案
本次修复分成两部分:
一、修复网络路径
- 将 VMware 网络模式从
NAT改为Bridged - 自动桥接只保留真实 Wi-Fi / 有线网卡
- 在 Linux 中刷新
ens33的 DHCP 租约 - 确认虚拟机获得新的桥接地址
10.113.233.121
二、修复依赖配置和服务状态
- 启动或确认所有依赖容器正常运行
- 确认 MySQL、MongoDB、Redis、RabbitMQ、Elasticsearch 的端口都可从 Windows 访问
- 将配置文件中所有旧的
192.168.201.101统一替换为新的桥接地址10.113.233.121 - 不只修改 MySQL,同时检查:
- MySQL
- MongoDB
- Redis
- RabbitMQ
- Elasticsearch
- MinIO
- 重新启动后端,确认出现:
text
Application startup complete.
当后端完整启动后,前端原先的 Vite proxy error 会自然消失。
复盘总结
这次问题最容易误导人的地方,是它一开始看上去像前端代理错误,接着又像数据库连接错误,但实际上它们都只是同一个底层问题的不同表现:Windows 到 VMware 虚拟机 Docker 服务端口不可达。
以后遇到类似问题,可以直接按下面的顺序处理:
- 先判断前端报错是不是后端未完成启动引起的
- 再判断后端是没执行,还是启动阶段失败退出
- 不要只盯第一个依赖报错,先怀疑整条依赖访问路径
- 用
Test-NetConnection验证 TCP 端口,不要只看ping - 如果依赖都在虚拟机里,优先检查 VMware NAT / Bridge 网络模式
- 网络恢复后继续检查容器状态和端口监听
- 最后统一更新所有依赖配置地址
一句话总结:前端错误是入口,后端启动失败是现象,虚拟机网络模式和端口可达性才是根因。