崇左市网站建设_网站建设公司_JavaScript_seo优化
2025/12/24 23:38:18 网站建设 项目流程

因为开发需要使用带界面的仿真软件,而以往的使用习惯基本都是 SSH 登录虚拟机即可满足需求。

但这次遇到两个现实问题:

  • 现有虚拟机系统为Ubuntu 18.04
  • 仿真软件要求Ubuntu 22.04 + GUI

最终选择的方案是:

  • 基于 Docker 构建一套Ubuntu 22.04 + 仿真软件的镜像
  • 运行在原有虚拟机中
  • 结合VMware Horizon,通过浏览器访问桌面,实现软件可视化操作

也正是在这个组合下,踩到了Docker 与 Horizon 的一个隐藏但非常典型的坑

也尝试过使用 MobaXterm 弹窗,根本弹不了远程虚拟机上的容器程序,AI 说可以是骗人的。


一、Horizon 是什么

VMware Horizon 本质上是一套VDI(虚拟桌面基础架构)解决方案。

简单理解就是:

  • 后端运行着大量云服务器 / 虚拟机
  • 虚拟机具备完整桌面环境(Linux / Windows)
  • 用户可通过浏览器(Web)或客户端访问远程桌面

在此前的实际使用中:

  • 日常运维、开发:SSH 完全够用
  • Horizon 桌面更多是“存在但几乎不用”的状态

但当GUI 仿真工具加入后,情况就完全不同了。


二、问题现象:安装 Docker 后,Horizon Web 桌面不可用

在虚拟机中安装 Docker 并启动后,出现了一个非常反直觉的现象:

  • SSH 登录、命令行操作一切正常
  • Horizon Web 桌面无法打开

浏览器直接报错:

An error has occurred: {"errno":"ETIMEDOUT","code":"ETIMEDOUT","syscall":"connect","address":"172.17.0.1","port":22443}

关键点非常集中:

172.17.0.1:22443

172.17.0.1,正是 Docker 默认创建的docker0网桥地址。


三、问题根因:Docker 默认网桥优先级与 Horizon 网络路径冲突

1️⃣ 先厘清:Horizon Web 桌面是如何建立连接的?

Horizon Web(Blast / HTML Access)并不只有一种连接模式,常见有两种:

模式一:浏览器直连虚拟机(Direct Connection)

  • 浏览器直接访问:虚拟机IP:22443
  • Blast 服务监听地址为:
0.0.0.0:22443
  • 网络路径:
浏览器 → 虚拟机 → Blast Server
模式二:通过中转服务器访问(Blast Secure Gateway / Unified Access Gateway)
  • 浏览器先连接 Horizon 中转服务器
  • 由中转服务器回连虚拟机的 Blast 服务端口
  • 网络路径:
浏览器 → Horizon 中转服务器 → 虚拟机 → Blast Server

本次问题环境使用的是第二种(中转模式),该模式可在 Horizon 管理台中配置。

2️⃣ 为什么会“连到” 172.17.0.1?

需要特别强调的是:

这并不是 Blast 监听地址配置错误,而是 Linux 系统选路问题。

Blast 服务本身监听的是:

0.0.0.0:22443

这意味着:

  • Blast 并不绑定某个具体 IP
  • 实际使用哪个 IP,对它来说取决于操作系统的网络选路结果

真正出问题的地方在于:

Linux 在选择“对外通信地址”时,选错了网卡。

3️⃣ Docker 实际造成了什么影响(真正的根因)

Docker 启动后会自动完成以下操作:

  • 创建docker0网桥
  • 默认分配地址:
172.17.0.1/16
  • 同时调整系统路由表与 iptables 规则

在部分环境中,会出现以下情况:

  • docker0网卡在路由或接口优先级上
    高于真实业务网卡
  • 系统在选择“回包路径”或“源地址”时
    优先选用了 docker0 的地址(172.17.0.1)

于是,实际发生的网络行为变成了:

Horizon 中转服务器 → 虚拟机 ↳ 系统选路:docker0 (172.17.0.1) ↳ Blast :22443

结果就是:

  • Horizon 中转服务器尝试连接172.17.0.1:22443
  • 该地址仅在虚拟机本地 Docker 网桥存在
  • 对外部网络完全不可达

最终表现为:

ETIMEDOUT

4️⃣ 补充:虚拟机访问地址的来源

需要注意的是:

虚拟机的访问地址是由 Horizon Agent 上报给 Connection Server / Gateway 的

当系统在某些场景下:

  • 选用了 docker0 对应的地址作为“对外地址”

那么 Agent 上报的地址本身就是不可达的,这也是问题产生的根源之一。

5️⃣ 结论

这并不是:

“Docker 抢占了 Blast 的端口”

而是:

Docker 创建的 docker0 网桥,在系统选路/接口优先级上高于真实网卡,
导致 Horizon 中转回连流量被引导到一个外部不可达的地址。

这也解释了为什么:

  • SSH 完全正常
  • 虚拟机本身运行无异常
  • 只有Horizon Web 桌面无法访问

因为只有 Horizon(尤其是中转模式)

👉强依赖“系统最终选择哪个 IP 作为对外通信地址”。


四、解决方案(可行但偏工程化)

最终采用的解决方式并不优雅,但非常稳定:

删除 docker0 → 登录 Horizon 桌面 → 重启 Docker

iplinksetdocker0 downiplinkdelete docker0# 用户成功登录 Horizon 桌面后systemctl restartdocker# docker0 会被重新创建

后续断开并重新连接 Horizon 桌面也可以正常访问(可能与会话 / 地址缓存有关)。

并不是所有虚拟机都会触发该问题
且实际需要桌面(GUI 仿真)的用户数量有限
同时虚拟机 IP 均为 DHCP 分配,无法批量在 Horizon Agent 中固定地址

因此最终选择了这种最小改动、可控范围内的工程方案

关于修改 Docker 网桥地址的误区

曾尝试通过修改 Docker 网关配置:

"bip":"10.99.99.1/24"

来规避172.17.0.1,但实践发现:

  • 问题并未彻底解决
  • 根因并非“占用了 172.17.0.1 本身”
  • 而是docker0 作为接口参与系统选路时的优先级问题

另外还踩过一个小坑:

  • Horizon 服务未停止时
  • Docker 启动阶段可能仍会受到影响

最终采用的顺序是:

  1. 停止 Horizon Web / Agent 服务
  2. 启动 Docker
  3. 再启动 Horizon

五、另一类常见报错的排查思路

如果不是 172.17.0.1 相关报错,而是:

“无法进入桌面,请联系管理员”

则可以按以下顺序排查。

检查 Horizon Agent 服务

systemctl status viewagent

必要时重启:

systemctl restart viewagent

检查 Blast 服务端口

netstat-tlnp|grep22443

期望看到:

tcp 0 0 0.0.0.0:22443 LISTEN xxx/VMwareBlastS

检查 iptables 影响

Docker 会自动修改 iptables,可能影响 Blast 通信。

可临时验证:

iptables -F iptables -L

仅用于排错验证,生产环境请谨慎

如果最终浏览器访问 Horizon 出现:

ETIMEDOUT 172.17.0.1:22443

基本可以确认仍是 docker0 选路问题,按前述方式处理即可。


六、Docker + GUI:DISPLAY

桌面能正常访问,并不代表容器里的 GUI 程序就能显示。

宿主机(虚拟机)准备

echo$DISPLAY

例如:

:102

并执行:

xhost +

仅限内网 / 临时调试使用

Docker 启动示例

dockerrun --net=host --rm -it\-eDISPLAY=$DISPLAY镜像bash

测试

aptinstall-y x11-apps xclock

能够弹窗即说明 GUI 显示链路打通。


七、批量环境治理

既然 Docker 在后续场景中是必需组件,那就统一在虚拟机上提前安装,并批量为现有用户授予 Docker 使用权限,避免后续重复配置和权限问题。

ansible 虚拟机组 -m shell -a'apt install -y docker.io'ansible 虚拟机组 -m shell -a\'for user in $(ls /home | grep -vE "^(public|gerrit|lost\+found)$"); do usermod -aG docker "$user" && echo "用户 $user 已加入 docker 组" done'

总结

本文问题本质并非端口或服务异常,而是 Docker 默认网桥参与系统选路,导致 Horizon 回连路径选错接口。
在依赖回连机制的 VDI 场景中,Docker 网络与桌面访问路径必须明确隔离或有序控制。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询