【无标题】

故障记录: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 等依赖时失败退出。

这个问题的关键点有三个:

  1. ping 通只说明网络层可达,不代表应用依赖的 TCP 端口可达。
  2. 后端依赖都部署在同一台 Linux 虚拟机中,因此第一个报错的 MySQL 只是最先暴露的问题,不是唯一问题。
  3. 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 : True
  • TcpTestSucceeded : 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 DirectBluetooth 等虚拟或旁路适配器:

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 容器没有运行,而不是桥接又失效了。这说明网络恢复以后,仍然要继续检查具体服务实例状态。

修复方案

本次修复分成两部分:

一、修复网络路径

  1. 将 VMware 网络模式从 NAT 改为 Bridged
  2. 自动桥接只保留真实 Wi-Fi / 有线网卡
  3. 在 Linux 中刷新 ens33 的 DHCP 租约
  4. 确认虚拟机获得新的桥接地址 10.113.233.121

二、修复依赖配置和服务状态

  1. 启动或确认所有依赖容器正常运行
  2. 确认 MySQL、MongoDB、Redis、RabbitMQ、Elasticsearch 的端口都可从 Windows 访问
  3. 将配置文件中所有旧的 192.168.201.101 统一替换为新的桥接地址 10.113.233.121
  4. 不只修改 MySQL,同时检查:
    • MySQL
    • MongoDB
    • Redis
    • RabbitMQ
    • Elasticsearch
    • MinIO
  5. 重新启动后端,确认出现:
text 复制代码
Application startup complete.

当后端完整启动后,前端原先的 Vite proxy error 会自然消失。

复盘总结

这次问题最容易误导人的地方,是它一开始看上去像前端代理错误,接着又像数据库连接错误,但实际上它们都只是同一个底层问题的不同表现:Windows 到 VMware 虚拟机 Docker 服务端口不可达。

以后遇到类似问题,可以直接按下面的顺序处理:

  1. 先判断前端报错是不是后端未完成启动引起的
  2. 再判断后端是没执行,还是启动阶段失败退出
  3. 不要只盯第一个依赖报错,先怀疑整条依赖访问路径
  4. Test-NetConnection 验证 TCP 端口,不要只看 ping
  5. 如果依赖都在虚拟机里,优先检查 VMware NAT / Bridge 网络模式
  6. 网络恢复后继续检查容器状态和端口监听
  7. 最后统一更新所有依赖配置地址

一句话总结:前端错误是入口,后端启动失败是现象,虚拟机网络模式和端口可达性才是根因。

相关推荐
geovindu2 小时前
java:Abstract Factory Pattern
java·开发语言·后端·设计模式·抽象工厂模式·创建型模式
geovindu2 小时前
java: Factory Method Pattern
java·开发语言·后端·设计模式·工厂方法模式·创建型模式
voicelen2 小时前
一通电话背后有多少角色?我拆了 Voicelen 的调度台给你看
后端
用户8017220416392 小时前
BarQode:C# 条码二维码生成库
后端
考虑考虑2 小时前
kafka4安装
后端·kafka·自动化运维
orient2 小时前
慢查询优化 10 招:从 EXPLAIN 到索引重建
后端
HAPPY酷2 小时前
【ROS2】VMware + Docker 运行 Gazebo 崩溃与“假死”排查实录
qt·docker·容器
用户40966601317512 小时前
MySQL 事务与锁机制实战:从隔离级别到死锁排查
后端