[WSL2] 解决 WSL2 中 Docker 部署的 SearXNG 重启后,localhost 不能用的问题

WSL2 中 Docker 部署的 SearXNG 在 Windows 无法通过 localhost 访问的排查与解决

日期: 2026-05-29

环境: Windows 11 (10.0.26200.8457) + WSL2 2.5.7.0 + Docker (Linux 原生,非 Docker Desktop)


1. 问题描述

在 WSL2 的 Docker 容器中部署了 SearXNG 搜索引擎服务,WSL2 内部访问正常,但 Windows 浏览器访问 http://localhost:8888 无法打开页面。

现象

测试方式 结果
WSL2 内: curl http://127.0.0.1:8888 ✅ HTTP 200
Windows: curl.exe http://localhost:8888 ❌ exit code 7(连接拒绝)
Windows: curl.exe http://172.18.14.110:8080 ✅ HTTP 200

2. 根因分析

问题的核心是 WSL2 网络模式与 Docker 网络模式的组合导致端口未映射到 Windows localhost,由以下三个因素叠加造成:

2.1 .wslconfig 格式错误 → mirrored 模式未生效

用户配置了 networkingMode=mirrored(该模式会让 WSL2 与 Windows 共享网络栈,localhost 互通),但 .wslconfig 文件缺少必需的 [wsl2] section header:

错误的配置:

ini 复制代码
networkingMode=mirrored
autoProxy=true

正确的配置:

ini 复制代码
[wsl2]
networkingMode=mirrored
autoProxy=true

文件位置: C:\Users\<用户名>\.wslconfig

没有 [wsl2] section header,WSL2 启动时忽略所有配置项,回退到默认的 NAT 模式。在 NAT 模式下,WSL2 拥有独立的虚拟网卡和 IP 地址,Windows 的 localhost 不会自动路由到 WSL2。

2.2 Docker 使用 bridge 网络 + docker-proxy 端口转发

原始容器创建命令使用了 Docker 默认的 bridge 网络模式:

bash 复制代码
docker run -d --name searxng -p 8888:8080 ... ghcr.io/searxng/searxng:latest

-p 8888:8080 的含义:

  • 容器内 granian 监听 8080 端口
  • docker-proxy 进程在 WSL2 的 0.0.0.0:8888 上监听并转发

关键点docker-proxy 绑定在 WSL2 的网络命名空间 内,而非 Windows 的网络栈。在 NAT 模式下,Windows localhost 不会自动转发到 WSL2 的端口。

2.3 SearXNG 端口配置的坑

SearXNG 镜像内部通过环境变量 GRANIAN_PORT=8080 指定监听端口。即使 settings.yml 中配置了 port: 8888,实际监听端口仍由 GRANIAN_PORT 环境变量决定(默认 8080)。这导致:

  • -p 8888:8080 → Windows 期望 8888,容器实际监听 8080,映射关系正确
  • 改用 --network host 后,容器直接使用 WSL2 网络栈,SearXNG 监听 8080(非 8888)

3. 网络架构图

NAT 模式(当前实际状态)

复制代码
┌─────────────────────────────────────────────┐
│  Windows                                    │
│  localhost:8888 ← ❌ 无路由                  │
│  172.18.14.110:8080 ← ✅ 可达                │
│                                             │
│  ┌───────────────────────────────────────┐  │
│  │  WSL2 (NAT, IP: 172.18.14.110)       │  │
│  │                                       │  │
│  │  ┌─────────────────────────────────┐  │  │
│  │  │  Docker bridge network          │  │  │
│  │  │  container IP: 172.17.0.x      │  │  │
│  │  │  granian → :8080               │  │  │
│  │  └─────────────────────────────────┘  │  │
│  │          ↕ docker-proxy               │  │
│  │  0.0.0.0:8888 (WSL2 命名空间)         │  │
│  └───────────────────────────────────────┘  │
└─────────────────────────────────────────────┘

Mirrored 模式(修复后)

复制代码
┌─────────────────────────────────────────────┐
│  Windows + WSL2 (共享网络栈)                 │
│  localhost:8080 ← ✅ 直接可达                 │
│                                             │
│  ┌───────────────────────────────────────┐  │
│  │  Docker host network                  │  │
│  │  granian → :8080 (直接在宿主网络)      │  │
│  └───────────────────────────────────────┘  │
└─────────────────────────────────────────────┘

4. 解决方案

提供三种方案,按推荐程度排序:

方案一:修复 .wslconfig + Docker host 网络(推荐 ✅)

步骤 1 :修复 .wslconfig

编辑 C:\Users\<用户名>\.wslconfig

ini 复制代码
[wsl2]
networkingMode=mirrored
autoProxy=true

步骤 2:重启 WSL 使配置生效

在 Windows PowerShell 中:

powershell 复制代码
wsl --shutdown

然后重新打开 WSL 终端。

步骤 3:重建 SearXNG 容器,使用 host 网络

bash 复制代码
# 获取卷路径
CONFIG_VOL=$(docker inspect searxng --format '{{range .Mounts}}{{if eq .Destination "/etc/searxng"}}{{.Source}}{{end}}{{end}}')
CACHE_VOL=$(docker inspect searxng --format '{{range .Mounts}}{{if eq .Destination "/var/cache/searxng"}}{{.Source}}{{end}}{{end}}')

# 停止并删除旧容器
docker stop searxng && docker rm searxng

# 使用 host 网络重建
docker run -d \
  --name searxng \
  --restart unless-stopped \
  --network host \
  -v ${CONFIG_VOL}:/etc/searxng \
  -v ${CACHE_VOL}:/var/cache/searxng \
  ghcr.io/searxng/searxng:latest

步骤 4:验证

  • Windows 浏览器访问 http://localhost:8080

优点:一劳永逸,WSL2 与 Windows 完全共享网络栈,所有服务均可通过 localhost 互访。

缺点:需要重启 WSL,会中断 WSL 中正在运行的所有进程。


方案二:netsh 端口代理(无需重启 WSL)

在 Windows PowerShell(管理员)中执行:

powershell 复制代码
# 获取当前 WSL IP
$wslIp = wsl hostname -I
$wslIp = $wslIp.Trim().Split()[0]

# 设置端口代理: localhost:8888 → WSL_IP:8080
netsh interface portproxy add v4tov4 `
  listenport=8888 listenaddress=127.0.0.1 `
  connectport=8080 connectaddress=$wslIp

# 可选:允许局域网访问
netsh interface portproxy add v4tov4 `
  listenport=8888 listenaddress=0.0.0.0 `
  connectport=8080 connectaddress=$wslIp

验证:

powershell 复制代码
netsh interface portproxy show all

优点:即时生效,无需重启 WSL。

缺点

  • 需要管理员权限
  • WSL IP 每次重启可能变化,需重新执行
  • 可被 Windows 防火墙拦截,需添加入站规则

方案三:自动端口代理脚本(方案二的自动化)

将以下脚本保存到 C:\Users\<用户名>\Desktop\setup_searxng_proxy.bat,每次 WSL 重启后以管理员身份运行:

bat 复制代码
@echo off
:: SearXNG 端口代理设置脚本
:: 需要以管理员身份运行

echo === SearXNG Port Proxy Setup ===

:: 获取 WSL IP
for /f "tokens=1" %%a in ('wsl hostname -I') do set WSL_IP=%%a
echo WSL IP: %WSL_IP%

:: 清除旧代理
netsh interface portproxy delete v4tov4 listenport=8888 listenaddress=127.0.0.1 >nul 2>&1
netsh interface portproxy delete v4tov4 listenport=8888 listenaddress=0.0.0.0 >nul 2>&1

:: 设置新代理
netsh interface portproxy add v4tov4 listenport=8888 listenaddress=127.0.0.1 connectport=8080 connectaddress=%WSL_IP%
netsh interface portproxy add v4tov4 listenport=8888 listenaddress=0.0.0.0 connectport=8080 connectaddress=%WSL_IP%

echo.
echo === Current Port Proxy Rules ===
netsh interface portproxy show all
echo.
echo SearXNG: http://localhost:8888
pause

5. 排查过程记录

第一步:确认服务状态

bash 复制代码
# WSL2 内部验证
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8888
# → 200 ✅

# Docker 容器状态
docker ps --filter name=searxng
# → Up, 端口 0.0.0.0:8888->8080/tcp

第二步:确认 Windows 侧连通性

powershell 复制代码
# Windows PowerShell
curl.exe http://localhost:8888
# → curl: (7) Failed to connect to localhost port 8888 ❌

# 通过 WSL IP
curl.exe http://172.18.14.110:8080
# → HTTP 200 ✅

结论:服务本身正常,问题在网络层------Windows localhost 未路由到 WSL2。

第三步:检查 WSL2 网络模式

bash 复制代码
# 检查 WSL2 IP
ip addr show eth0 | grep inet
# → 172.18.14.110/20 ← NAT 模式的特征(mirrored 模式下 eth0 应与 Windows 共享 IP)

# 检查 .wslconfig
cat /mnt/c/Users/comed/.wslconfig
# → networkingMode=mirrored  ← 缺少 [wsl2] header!

发现根因:.wslconfig 格式错误导致 mirrored 模式未生效。

第四步:检查 Docker 网络模式

bash 复制代码
docker inspect searxng --format '{{.HostConfig.NetworkMode}}'
# → bridge

docker inspect searxng --format '{{json .HostConfig.PortBindings}}'
# → {"8080/tcp":[{"HostIp":"","HostPort":"8888"}]}

bridge 模式下 docker-proxy 在 WSL2 命名空间内监听,Windows localhost 无法直达。

第五步:确认 SearXNG 实际监听端口

bash 复制代码
docker inspect searxng --format '{{range .Config.Env}}{{println .}}{{end}}' | grep PORT
# → GRANIAN_PORT=8080

容器内 granian 监听 8080,而非 settings.yml 中的 8888。


6. 关键知识点

WSL2 网络模式对比

特性 NAT(默认) Mirrored
WSL2 有独立 IP ✅ (172.x.x.x) ❌ (共享 Windows IP)
localhost 互通
外部设备访问 WSL 需端口转发 直接可达
.wslconfig 配置 不需要 [wsl2] header 必需
WSL 最低版本 --- 2.0+

Docker 网络模式对比(WSL2 环境下)

特性 bridge + -p host
容器有独立 IP ❌ (共享宿主网络)
端口映射 需要 -p 不需要(直接监听宿主端口)
Windows localhost 可达 ❌ (NAT 模式下) ❌ (NAT 模式下)
mirrored 模式下 Windows 可达
端口冲突风险

SearXNG 端口优先级

复制代码
GRANIAN_PORT 环境变量 > settings.yml 中的 port 配置 > 默认值 8080

7. 当前环境信息

项目
Windows 版本 10.0.26200.8457
WSL 版本 2.5.7.0
WSL 内核 6.6.87.1-1
Docker Linux 原生 (非 Docker Desktop)
SearXNG 镜像 ghcr.io/searxng/searxng:2026.5.23
SearXNG Web Server granian (GRANIAN_PORT=8080)
当前 WSL IP 172.18.14.110
当前 Docker 网络模式 host
.wslconfig 已修复 (含 [wsl2] header)

8. 待完成操作

  • 执行 wsl --shutdown 重启 WSL,使 mirrored 模式生效

  • 重启后验证 Windows http://localhost:8080 可访问 SearXNG

  • 确认 mirrored 模式生效后,可选择删除端口代理规则:

    powershell 复制代码
    netsh interface portproxy delete v4tov4 listenport=8888 listenaddress=127.0.0.1
    netsh interface portproxy delete v4tov4 listenport=8888 listenaddress=0.0.0.0

文档生成时间: 2026-05-29 22:35 (Asia/Shanghai)

相关推荐
ai产品老杨2 小时前
突破异构算力与多协议壁垒:基于 Docker+边缘计算的企业级 AI 视频管理平台架构解析
人工智能·docker·边缘计算
“码”力全开14 小时前
打破芯片与协议壁垒:基于 Docker + 边缘计算的 GB28181/RTSP 视频智能管理平台架构设计与源码交付方案
docker·音视频·边缘计算
Albert Edison17 小时前
【Docker】Ubuntu22.04 安装 Docker 教程
运维·docker·容器
AI服务老曹18 小时前
基于Docker的低代码AI视频管理平台架构解析:打通GB28181/RTSP多协议,支持异构边缘计算与全源码交付
人工智能·低代码·docker
codefan※18 小时前
一键部署私人 LLM:Ollama + Docker 极简指南
运维·docker·容器·大模型·llm·本地部署·ollama
IT策士21 小时前
Docker 网络进阶:容器间通信与 DNS 解析
网络·docker·容器
热爱Liunx的丘丘人1 天前
Docker Compose 实现 Nginx 与 MySQL 多容器服务编排
mysql·nginx·docker
热爱Liunx的丘丘人1 天前
Docker
运维·docker·容器
sszdzq1 天前
docker 安装 rocketmq + dashboard
docker·容器·rocketmq