
Windows 下通过 WSL2 部署 WeKnora(本机定制版)
Windows 下通过 WSL2 部署 WeKnora(本机定制版)
本文基于官方
README_CN.md快速开始与.env.example(main 分支,2026-09 核对)整理,
并按本机实测环境做了定制:已完成的步骤给出复核命令,待执行的步骤给出本机实值。
全程不使用表格;所有<尖括号>都是需要自行替换的占位符,本机对应的真实值见第十五节。
一、本机环境实况(2026-09-25 实测)
硬件
- 系统:Windows 11
- CPU:AMD Ryzen 7 7700(8 核 16 线程,Zen4)
- 内存:64 GB
- 独显:AMD Radeon RX 9070 XT 16 GB(RDNA4 / gfx1200),驱动 32.0.31041.1004
- 另有 CPU 核显 AMD Radeon Graphics(gfx1036),Ollama 默认忽略
软件就绪状态
- WSL2:已装,默认发行版 Ubuntu-24.04(VERSION 2,Running),WSL 用户名
<WSL用户名> - 另有
docker-desktop发行版(Docker Desktop 自动创建,正常现象,不要动它) - Docker Desktop:已装并接入 Ubuntu-24.04;WSL 内实测 Engine 29.8.0、Compose v2 5.5.1
- Docker 数据盘:
M:\Docker\wsl\DockerDesktopWSL(不在 C 盘,正确) - 镜像加速:已配
https://docker.m.daocloud.io/,拉镜像不用再换源 - Ollama 0.34.2 装在 Windows 宿主:
C:\Users\<Windows用户名>\AppData\Local\Programs\Ollama\ollama.exe - 本机 Ollama 模型:
bge-m3(向量模型,1024 维)——已实测 100% GPU 跑通,可直接用qwen3.5:9b(6.6 GB)、granite4.1:8b(5.3 GB)——当前启动失败,见第六节deepseek-v4-flash:cloud、gemma4:31b-cloud、minimax-m3:cloud——Ollama 云模型,实测返回 402(未充值/未订阅,不可用)
- 端口:Windows 侧 80、8080 当前空闲,无需改映射端口
- WSL 根分区 1 TB,剩余约 955 GB,空间充足
- WeKnora 仓库:已克隆 v0.8.2 到
~/WeKnora(2026-09-25,.env已从模板生成,待编辑) - WSL DNS:已固定为
223.5.5.5/119.29.29.29(原自动 NAT DNS 不可用,见 13.3)
资源配额(C:\Users\<Windows用户名>\.wslconfig 实测内容)
[wsl2]
memory=16GB
processors=8
swap=8GB
localhostForwarding=true
[experimental]
autoMemoryReclaim=gradual
sparseVhd=true含义:WSL(以及全部容器)上限 16 GB;Windows 侧的 Ollama 不受此限制,可用宿主全部 64 GB 和独显。
还差三件事
- Windows 上 Ollama 当前只监听
127.0.0.1,且未设置OLLAMA_HOST——容器会连不上,必须开放监听并重启(第六节)。 - 本地 8B/9B 对话模型 Vulkan 显存分配失败——LLM 先走远端 OpenAI 兼容 API(方案 C),或修好本地后再切。
docker compose pull && up(仓库与.env均已就绪,仅剩第八节)。
二、先选路线(本机已定)
官方有标准版 Docker Compose、Lite 单二进制、Helm、桌面应用等形态。Windows 单机现实可选前两种:
- 标准版 Docker Compose(本文主线,本机采用)
- 数据库 ParadeDB(PostgreSQL 17),队列 Redis + Asynq,核心容器 5 个:
frontend(Nginx)、app(Go 后端)、docreader(文档解析)、postgres、redis。 - 可选 profile:
neo4j(知识图谱)、minio(对象存储)、langfuse(链路追踪)、searxng(联网搜索)、odl-hybrid(重型解析)、sandbox、qdrant/milvus/weaviate/doris(外部向量库)、dex(OIDC);full会拉起除向量库/odl 外的大部分。 - 本机 16 GB WSL 配额下只跑核心服务,不要上来就
--profile full。
- 数据库 ParadeDB(PostgreSQL 17),队列 Redis + Asynq,核心容器 5 个:
- Lite 单二进制:SQLite + 内存队列,无 Docker。简版步骤见第十四节。
本机模型组合(推荐)
- 向量模型 Embedding:本机 Ollama 的
bge-m3(已验证 GPU 可用,零 API 费用)。 - 对话模型 LLM:远端 OpenAI 兼容 API(DeepSeek / 通义 / 智谱等,按量付费最省事);
等本地 Vulkan 问题修好后,可在设置里随时切回qwen3.5:9b/granite4.1:8b,不影响已建索引。
三、整体结构:三层各管什么
容器拓扑如下(与 pic/标准 Docker 部署.png 一致,GitHub / 装了 Mermaid 插件的 VS Code 预览可直接渲染):

图 1|标准 Docker 部署的容器拓扑。
- Windows 宿主:Docker Desktop(WSL2 后端)、Ollama(占独显与宿主内存)、浏览器、远端 API 的网络出口。
- WSL2(Ubuntu-24.04):敲
docker compose命令、存放仓库代码(/home/<WSL用户名>/WeKnora)。 - 容器内部:
WeKnora-frontend:Nginx,宿主80→ 容器80WeKnora-app:Go 后端,宿主8080→ 容器8080,健康检查/healthWeKnora-docreader:gRPC50051,只在 compose 内网暴露,不映射宿主WeKnora-postgres:paradedb/paradedb:v0.22.6-pg17WeKnora-redis:redis:7.0-alpine
容器访问 Windows 宿主上的 Ollama,统一走 Docker Desktop 提供的别名 host.docker.internal。
四、第一步:WSL2 + Ubuntu(本机已完成,只需复核)
本机已经装好 Ubuntu-24.04 且默认版本为 WSL2。管理员 PowerShell 复核:
wsl -l -v
# 期望看到:
# NAME STATE VERSION
# * Ubuntu-24.04 Running 2
# docker-desktop Running 2全新机器才需要的安装命令(本机无需执行,留作重建参考):
wsl --install -d Ubuntu-24.04
wsl --set-default-version 2进入 Ubuntu,更新系统并确认用户名(本机是 <WSL用户名>):
sudo apt update && sudo apt upgrade -y
whoami # 本机输出 <WSL用户名>五、第二步:Docker Desktop 接入 WSL2(本机已完成,只需复核)
本机 Docker Desktop 已配置:WSL2 引擎、对 Ubuntu-24.04 的集成开关已打开、
数据目录在 M:\Docker\wsl\DockerDesktopWSL、Registry mirror 为 daocloud。
在 Ubuntu 终端里复核(建议全程统一在 Ubuntu 里操作 docker;Windows 侧其实也装了 docker CLI,两边混敲容易搞错上下文):
docker version --format '{{.Server.Version}}' # 本机实测 29.8.0
docker compose version --short # 本机实测 5.5.1
docker run --rm hello-world # 出现 Hello from Docker! 即正常全新机器的配置路径(本机已做完):
- 安装:
winget install -e --id Docker.DockerDesktop --accept-package-agreements --accept-source-agreements
(安装器下载慢时,用迅雷下Docker Desktop Installer.exe后...Installer.exe install --quiet --accept-license --backend=wsl-2 --wsl-default-data-root=M:\Docker\wsl-data)。 - Settings → General:勾选 Use the WSL 2 based engine。
- Settings → Resources → WSL Integration:打开 default distro 与 Ubuntu-24.04。
- Settings → Docker Engine 的
registry-mirrors加https://docker.m.daocloud.io/(本机已配)。 - Apply & Restart,等左下角 Running。
若 Ubuntu 里 docker: command not found,九成是第 3 步的发行版开关没打开。
六、第三步:模型服务
WeKnora 自身不含模型权重,必须有「LLM + Embedding」两类服务。本机 Ollama 已在 Windows 宿主上运行。
6.1 必做:开放 Ollama 监听,让容器能连进来(本机当前缺失)
Windows 上 Ollama 默认只监听 127.0.0.1,从 WSL/容器经非回环地址访问会被拒。
本机实测用户环境变量里 OLLAMA_HOST、OLLAMA_ORIGINS 均未设置,需补上。
在 Windows PowerShell 执行:
# 写入用户级环境变量(持久生效)
[Environment]::SetEnvironmentVariable('OLLAMA_HOST','0.0.0.0:11434','User')
[Environment]::SetEnvironmentVariable('OLLAMA_ORIGINS','*','User')
# 退出托盘里的 Ollama 后重新启动
Stop-Process -Name 'ollama*' -Force -ErrorAction SilentlyContinue
# 关键坑:SetEnvironmentVariable 只写注册表,当前 PowerShell 会话的环境不会更新,
# 而 Start-Process 继承的是当前会话的旧环境 —— 同一窗口里直接拉起 Ollama 会读不到新变量。
# 稳妥做法:从开始菜单重新启动 Ollama(由 explorer 启动,能拿到新变量);
# 或者在当前会话先补两行临时变量再拉起:
$env:OLLAMA_HOST='0.0.0.0:11434'; $env:OLLAMA_ORIGINS='*'
Start-Process "$env:LOCALAPPDATA\Programs\Ollama\ollama.exe" -ArgumentList 'app'Windows 侧先验证监听地址确实变了(比 curl 更直接):
netstat -ano | findstr :11434
# 期望看到 0.0.0.0:11434 处于 LISTENING;
# 若仍是 127.0.0.1:11434,说明 OLLAMA_HOST 没生效,九成是上面那个会话继承坑放通 Windows 防火墙入站(管理员 PowerShell,只需执行一次):
netsh advfirewall firewall add rule name="Ollama 11434" dir=in action=allow protocol=TCP localport=11434验证(在 WSL Ubuntu 里执行,地址用 WSL 网关,当前实测为 <WSL网关IP>,重启机器后可能变):
ip route show default | awk '{print $3}' # 查网关 IP,本机当前 <WSL网关IP>
curl http://<WSL网关IP>:11434/api/version # 能返回版本 ollama版本 JSON 即开放成功注意:放通后同一局域网内的设备理论上可访问你本机 Ollama。在可信家庭网络无碍;
公用网络下可在防火墙规则里把 remote IP 限定为 WSL 网段(如<你的WSL网段>)。
容器内的固定写法仍是别名(compose 网络帮你解析,不用关心网关 IP 变化):
OLLAMA_BASE_URL=http://host.docker.internal:114346.2 Embedding:本机 bge-m3(已就绪)
已实测通过:bge-m3 在 Ollama 上以 100% GPU 运行(Vulkan 后端,常驻约 664 MB,输出 1024 维向量)。
若重装过 Ollama,重新拉取即可:
ollama pull bge-m3
ollama list约束:Embedding 模型一旦用于建库就不要再换;换模型等于全部向量作废,必须重建索引。
WeKnora 里向量模型名不是写在 .env 里的,而是在首次初始化向导 /「设置 → 模型」中填写 bge-m3。
6.3 LLM:本地大模型当前有故障,本期推荐走远端 API
本机两个本地对话模型实测均启动失败:
- 日志(
%LOCALAPPDATA%\Ollama\server.log)显示 9070 XT 通过 Vulkan 后端被发现(15.9 GiB),
但加载 8B/9B 时报failed to allocate Vulkan0 buffer ... ErrorOutOfDeviceMemory,
即使把上下文降到 2048 也失败;不是物理显存不够(权重只有 5–6 GB),是 Vulkan 分配层问题。 - 日志另有告警:
user overrode visible devices HIP_VISIBLE_DEVICES=1(本机存在该环境变量覆盖)。
方案 C:远端 OpenAI 兼容 API(本期推荐)
注册并拿到任一服务的 API Key(DeepSeek 性价比高,通义/智谱/自建网关均可):
- DeepSeek:Base URL
https://api.deepseek.com/v1,模型名如deepseek-chat - 通义千问:Base URL
https://dashscope.aliyuncs.com/compatible-mode/v1,模型名如qwen-plus - 智谱:Base URL
https://open.bigmodel.cn/api/paas/v4,模型名如glm-4-flash
Key 不用写进 .env:标准版在首次注册登录后的初始化向导、或「设置 → 模型」里添加
provider=OpenAI 兼容、Base URL、API Key、模型名即可。需要在启动前预置时,才用
仓库的 config/builtin_models.yaml.example(复制为 config/builtin_models.yaml,
配合 .env 里的 LLM_MODEL_NAME / LLM_BASE_URL / LLM_API_KEY / LLM_PROVIDER=openai)。
已登录的 Ollama 云模型(
*-cloud)当前返回402 Payment Required,不充值不可用,不要选。
方案 A:修好后再用本地 LLM(可选,排障见第十三节)
想跑本地模型时,按第十三节 AMD 专节处理后,用:
ollama list # qwen3.5:9b / granite4.1:8b 已在本机
ollama run qwen3.5:9b "你好"
ollama ps # PROCESSOR 列必须显示 100% GPU,否则说明在 CPU 上慢推理修好后在 WeKnora 设置里把 LLM 切到 Ollama(模型名 qwen3.5:9b)即可,
Embedding 继续用 bge-m3,互不影响。
6.4 为什么不把 Ollama 装进 WSL(不推荐方案 B)
Docker Desktop 的 WSL2 后端不向 WSL 透传显卡;在 WSL 里另装 Ollama 走不了 9070 XT(纯 CPU),
还要和容器抢那 16 GB 配额。本机正确姿势就是 Ollama 留在 Windows(独占 64 GB + 独显),
容器经 host.docker.internal 调用。
资源预估:核心容器约吃 3–6 GB WSL 内存(docreader 内含 LibreOffice/Playwright,是大头);
Windows 侧 Ollama 推理用宿主内存,与 WSL 的 16 GB 互不占用——这正是方案 A 在本机的优势。
七、第四步:拉取代码与配置(7.1–7.3 已完成,剩第八节启动)
7.0 这些命令在哪里执行:先进入 WSL
本节及第八节的全部命令(git clone、cp .env.example .env、docker compose ...)都在
WSL 的 Ubuntu-24.04 终端里执行,不是 Windows 的 PowerShell / CMD。进入方式任选其一:
- 开始菜单搜索并打开 Ubuntu 24.04,看到
<WSL用户名>@...:~$提示符即成功; - Windows Terminal 顶部标签下拉,选 Ubuntu-24.04;
- 在 PowerShell 中执行
wsl -d Ubuntu-24.04。
进入后先做两条复核(本机 WSL 与 Docker Desktop 均已装好,正常应一次通过):
pwd # 应显示 /home/<WSL用户名>(进入后默认就在家目录,即 ~)
docker ps # 列出容器表头即正常;若报 cannot connect / permission denied,
# 说明 Docker Desktop 没开或未对该发行版启用 WSL 集成(回第五节复核)注意这不是「把 WeKnora 装进 WSL」,三层分工(见第三节)保持不变:
- WSL(Ubuntu-24.04):只放仓库与
.env配置(~/WeKnora),并在此敲docker compose; - Docker Desktop(WSL2 后端):WeKnora 的 5 个服务实际跑在容器里;
- Windows 宿主:Ollama、浏览器(部署完访问
http://localhost)。
唯一留在 Windows 侧做的前置动作是 6.1 给 Ollama 设置 OLLAMA_HOST——不要在 WSL 里设置。编辑 .env 可用 WSL 内的 vim,
也可在 Windows 侧 VS Code 装 WSL 扩展后用 Remote-WSL 打开仓库图形化编辑。
为什么项目命令必须在 WSL 里敲,Windows PowerShell 不行?
先澄清:docker compose 是在 Ubuntu shell 里执行的普通命令,不是「在容器中运行」,
也不需要先 docker exec 进容器。它的作用只是把指令发给 Docker 引擎,三层关系是:
Ubuntu 终端敲 docker compose ──▶ docker-desktop 发行版里的引擎 ──▶ 管理 5 个容器
(仓库和 .env 所在处) (同一个引擎,见第三节)Windows 侧的 docker.exe 连的是同一个引擎,纯观察命令(docker ps、docker logs、docker stats)在 PowerShell 里也能出结果;但本项目的编排命令不要在 Windows 侧跑:
- 相对路径 bind mount 会被解析错:compose 中有 3 处
./...挂载
(./config/config.yaml、searxng、dex 配置,2026-09-26 实测)。在 Windows 侧执行时
它们被展开成\\wsl.localhost\Ubuntu-24.04\home\...这样的 UNC 路径,不同 Docker Desktop
版本对 UNC 挂载行为不稳(path not shared 或挂进去是空文件),app 读不到配置会启动异常;
在 WSL 里执行则解析为原生 ext4 路径,零歧义。 ./scripts/start_all.sh是 bash 脚本,PowerShell 无法执行;- 跨边界还会叠加 CRLF、盘符、引号转义问题(见 13.4)。
实用边界:pull/up/down/logs/start_all.sh 等项目操作一律在 WSL 的 ~/WeKnora 里执行;docker ps 类只读观察命令两边皆可,但建议也统一在 WSL;浏览器访问 http://localhost
与命令在哪敲无关(端口映射由 Docker Desktop 维护)。
7.1 拉取代码(已完成)
状态:v0.8.2 已于 2026-09-25 克隆到
~/WeKnora(detached HEAD 正常),.env已从模板生成。
以下命令留档备侧重装/重建;克隆时曾遇Could not resolve host,排障见 13.3。
仓库必须放在 WSL 的 ext4 文件系统里(即 /home/<WSL用户名>/...),不要放 /mnt/c 或 /mnt/e。
跨 9P 挂载跑数据库卷,性能差且容易出锁。
# 在 Ubuntu 中执行
# ping www.google.com
cd ~
# rm WeKnora
git clone --branch v0.8.2 https://github.com/Tencent/WeKnora.git
cd WeKnora
cp .env.example .env
git describe --tags # 应输出 v0.8.2,确认检出的就是固定版本(此时处于 detached HEAD,正常)为什么固定 v0.8.2,而不是直接 clone 主分支:v0.8.2 是截至 2026-09-25 的最新稳定 release
(在 https://github.com/Tencent/WeKnora/releases 核对)。仓库里的 compose 模板、.env.example、
启动脚本会随main分支持续演进,可能跑到已发布镜像的前面造成错配。把仓库 git tag 与.env里的WEKNORA_VERSION同时钉在 v0.8.2,模板与镜像版本严格配套,日后重建也可复现。
想省事追官方稳定版,可以两者都用默认(clonemain+WEKNORA_VERSION=latest),但不要用
「main 分支配旧 tag」或「旧仓库配 latest」。升级时两个 tag 必须一起换(见后文「升级」小节)。
v0.8.2 更新条目那么多,是不是还不稳定?——更新多不等于核心不稳。把该 release 的 80 余条
PR 逐条分类后:约三分之一是新功能(本机浏览器 BrowserSkill、内置 MCP Server、对话分叉/追加、
沙箱交互终端、日语界面、博查搜索),过半是缺陷修复(飞书图片、Wiki 排序、文件预览、OCR 合并、
token 过期恢复等),少量重构与文档。churn 几乎全部集中在 0.8 系列新长出来的 Agent 沙箱 /
MCP / 浏览器技能上;本机主要使用的核心链路「文档解析 → ParadeDB 混合检索 → RAG 问答」
自 v0.3 起迭代一年多,本次基本没动,属于相对成熟的部分。判断依据与对策:
- 0.x 版本号的含义:按语义化版本,0.x 阶段官方不承诺 API/行为稳定;约 1–2 周一个版本
(v0.7.0→0.7.2→0.8.0→0.8.2)是年轻项目快速迭代的正常节奏。v0.8.2 在 GitHub 上是正式
Release(非 Pre-release),官网当前也主推它。- 安全反而是选新版的理由:v0.8.0 及更早版本有公开安全公告(跨租户访问控制、MCP 工具注入、
AI 数据库查询 SQL 注入、web_fetch 的 DNS rebinding SSRF 等),v0.8.2 已含相应修复
(如路径穿越修复 #3066)。个人本机部署暴露面小,但仍应选修复后的版本,而不是退回旧版。- Breaking change 对全新部署无影响:钉钉通道改 Stream-only、沙箱命令默认以 root 运行、
MCP 工具目录格式变更,只影响已在用旧版 MCP/钉钉集成的用户。- 新功能确有回炉现象:例如 #3181 上线沙箱实时文件管理后又被 #3188 Revert。对策就是第八节
的做法——只跑核心 5 容器,先不开sandbox/odl-hybrid等 profile。- 结论:单用户、数据在本地的个人知识库场景,v0.8.2 可放心使用;本文的四条对冲措施
(钉死 tag 不追 latest、80/8080 不暴露不可信网络、不开重型 profile、升级前备份)比纠结
版本号更重要。若极度求稳可退 v0.7.2(经 3 个补丁迭代),但会失去 MCP Server / 浏览器技能,
且需接受未修的安全公告,本机不建议。以后新 release 出来建议等 3–7 天观察有无回归报告再升级。
先澄清一个常见疑问:克隆仓库是为了拿
docker-compose.yml、.env.example、启动脚本与config/
模板,不是要自己构建镜像。WeKnora 的应用镜像(wechatopenai/weknora-ui、wechatopenai/weknora-app、wechatopenai/weknora-docreader、wechatopenai/weknora-sandbox)官方已发布在 Docker Hub,
tag 跟随WEKNORA_VERSION(默认latest;固定版本用带v前缀的 tag),第八节docker compose pull
直接拉取即可;数据库/队列用的是现成三方镜像(paradedb/paradedb、redis)。compose 文件里每个服务
虽然都带build:段,那是给开发者从源码构建用的(make build-images、docker compose up --build,
还需 Go/Node/Python 工具链),正常部署不会触发。唯一例外是odl-hybridprofile 的镜像,
官方明确「仅本地构建、不发布」,本机不开该 profile,不受影响。
GitHub 直连超时/极慢时:先给 git 配代理(
git config --global http.proxy http://<代理地址>:<端口>),
或改用可用的 GitHub 加速/镜像地址重试。注意本机的 daocloud 加速只管 docker 镜像拉取,不管 git。
7.2 编辑 .env(已完成)
编辑 .env(vim .env,或在 VS Code 里用 Remote-WSL 打开仓库后编辑)。
⚠️ 下面是需要填入
.env的值(本机已于 2026-09-26 按 7.3 规则生成并写入,本文以占位符给出)。
真实密码/密钥属于敏感信息:不要提交到任何 git 仓库、不要分享、
不要放进同步盘共享目录;请把生成后的值抄进密码管理器。
状态:已于 2026-09-26 写入 WSL~/WeKnora/.env(原模板备份为同目录.env.template-defaults.bak,权限 600,纯 LF),完整文件副本在配置文件示例/.env(与 WSL 内文件 md5 一致);docker compose config校验通过,
渲染确认五个值将在up时注入容器。容器尚未创建,等第八节pull/up。
7.2.1 需要填入的值(按 7.3 规则自行生成)
# ===== B1. 数据库(24 位十六进制,替换模板默认 postgres123!@#)=====
DB_USER=postgres
DB_PASSWORD=<24 位十六进制,用 openssl rand -hex 12 生成>
DB_NAME=WeKnora
# ===== B2. Redis(24 位十六进制,与 DB 密码不同;替换默认 redis123!@#)=====
REDIS_PASSWORD=<另生成的 24 位十六进制,勿与 DB 密码相同>
# ===== F1. 安全密钥(openssl rand -hex 32 → 64 字符)=====
JWT_SECRET=<64 位十六进制,用 openssl rand -hex 32 生成>
# AES-256 主密钥(openssl rand -hex 16 → 必须正好 32 字符;丢失不可恢复,升级沿用)
SYSTEM_AES_KEY=<32 位十六进制,用 openssl rand -hex 16 生成>
# SYSTEM_SIGNING_KEY 可选,保持留空,自动回退到 SYSTEM_AES_KEY
# ===== D1. 模型(指向 Windows 宿主的 Ollama,模板默认值就是它,保持即可)=====
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_OPTIONAL=true
# ===== A1/A3. 版本与端口(本机 80/8080 空闲,全部保持默认)=====
WEKNORA_VERSION=v0.8.2 # 必须与 clone 的 git tag 完全一致(带 v 前缀)
FRONTEND_PORT=80
APP_PORT=8080
# ===== 其他保持模板默认 =====
# DB_DRIVER=postgres / RETRIEVE_DRIVER=postgres / STREAM_MANAGER_TYPE=redis
# STORAGE_TYPE=local(本地磁盘存文件,无需 minio)
# TZ=Asia/Shanghai / AUTO_MIGRATE=true7.2.2 一键写入(WSL 里执行,替代手工 vim)
在 WSL 中执行以下命令,可把四个值(用上一步生成的结果替换变量)与版本号直接写入 ~/WeKnora/.env
(先备份原文件为 .env.template-defaults.bak;纯十六进制值无 $/空格,不存在转义问题):
cd ~/WeKnora
cp .env .env.template-defaults.bak
DB_PASSWORD='<你的 24 位十六进制>'
REDIS_PASSWORD='<另生成的 24 位十六进制>'
JWT_SECRET='<你的 64 位十六进制>'
SYSTEM_AES_KEY='<你的 32 位十六进制>'
sed -i \
-e 's|^WEKNORA_VERSION=.*|WEKNORA_VERSION=v0.8.2|' \
-e "s|^DB_PASSWORD=.*|DB_PASSWORD=$DB_PASSWORD|" \
-e "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=$REDIS_PASSWORD|" \
-e "s|^JWT_SECRET=.*|JWT_SECRET=$JWT_SECRET|" \
-e "s|^SYSTEM_AES_KEY=.*|SYSTEM_AES_KEY=$SYSTEM_AES_KEY|" \
.env
# 校验:应看到 5 行,且两个 24 位、一个 64 位、一个 32 位
grep -E '^(WEKNORA_VERSION|DB_PASSWORD|REDIS_PASSWORD|JWT_SECRET|SYSTEM_AES_KEY)=' .env生成命令本身在 Windows PowerShell 或 WSL 里都能用(两边均有 OpenSSL 3.x;
PowerShell 直接敲openssl rand -hex 16即可),生成的十六进制字符串与操作系统无关。
7.3 敏感值要求、密钥生成与注意事项
三个必改值分别是什么要求
DB_PASSWORD(PostgreSQL 密码)- 用途:
postgres容器(ParadeDB)中DB_USER=postgres用户的密码;compose 会把同一个值
同时注入数据库容器和 app,两边天然一致,不需要也不要分别设置。 - 模板默认
postgres123!@#,长期使用必须改成自己的值。 - 长度建议 16 位以上,字母 + 数字即可(没必要硬塞特殊符号);不要包含
$和空格
(compose 解析.env时$xxx会被当变量插值);若一定要用其他特殊字符,给整个值加
英文双引号,如DB_PASSWORD="abc!@#xyz"。 - 首次启动时一次定好:postgres 容器只在数据卷首次初始化时使用该密码;事后改密码要
先在库内ALTER USER再同步改.env重建容器,属于自找麻烦。 - 不想自己想密码,可直接生成(纯十六进制、无任何转义风险):
openssl rand -hex 12→ 24 个字符。
- 用途:
REDIS_PASSWORD(Redis 密码)- 用途:
redis容器的访问密码(requirepass),同样由 compose 同时注入 redis 与 app。
模板默认redis123!@#,改掉默认值。 - 字符规则与
DB_PASSWORD完全相同(避免$、空格;可用openssl rand -hex 12另生成一个,
两个密码不要相同)。 - 模板注释允许留空(仅限完全可信的隔离内网);本机 80/8080 会绑定到 Windows 所有网卡,
Redis 端口虽不对外映射,但保持带密码是零成本的纵深防御,不要留空。 - 事后修改同样需要改 Redis 配置/重启 + 同步
.env,首次就定好。
- 用途:
SYSTEM_AES_KEY(AES-256 主密钥,最不能出错的一个)- 用途:对数据库里的敏感字段做落盘加密——各空间填写的模型 API Key、向量库凭证、
联网搜索 provider key、WeKnoraCloud AppSecret 等。 - 格式是硬性的:必须正好是 32 个十六进制字符(
0-9a-f),即openssl rand -hex 16的原样输出(16 字节随机数的 hex 编码 = 32 个 ASCII 字符)。
多一位、少一位、含非 hex 字符都不行。 - 留空或长度不对:服务不报错退出,但已加密的字段全部解不出来(设置页里 API Key
显示为空,需要逐个重新填写)。 - 丢失不可恢复:没有任何后门或重置流程,所有密文永久作废。生成后立刻存进密码管理器,
并随.env一起纳入备份。 - 升级时必须沿用原值:以后换版本只改
WEKNORA_VERSION,这个 key 原样保留
(官方注释原话:retain existing keys on upgrade)。 - 相关但不同的两个值,别混淆:
JWT_SECRET:登录刷新 Token 的签名密钥,openssl rand -hex 32(64 个十六进制字符);
留空时每次启动随机生成,症状是容器一重启所有人都要重新登录——所以也显式固定。
它丢了不丢数据,只是登录态失效。SYSTEM_SIGNING_KEY:可选,embed 会话签名/预签名链接用,openssl rand -hex 32;
留空自动回退到SYSTEM_AES_KEY,本机保持留空即可。
- 已废弃的旧变量名
TENANT_AES_KEY/CRYPTO_MASTER_KEY/CRYPTO_SALT主程序不再读取,
不要从旧教程里抄进来。
- 用途:对数据库里的敏感字段做落盘加密——各空间填写的模型 API Key、向量库凭证、
密钥生成命令(Windows PowerShell / WSL 均可执行)
openssl rand -hex 32 # → JWT_SECRET(64 个十六进制字符)
openssl rand -hex 16 # → SYSTEM_AES_KEY(32 个十六进制字符,AES-256)
openssl rand -hex 12 # → 可作为 DB_PASSWORD / REDIS_PASSWORD(24 个字符,各执行一次取不同结果)本机四个值已于 2026-09-26 用 Windows 侧 OpenSSL 3.5.6 生成,需填入的值见
7.2.1(文中以占位符给出);重新部署/怀疑泄露时可用上面命令重新生成并整体替换
(注意:SYSTEM_AES_KEY在首次启动写入数据后不可更换,否则旧密文全部解不开)。
其他注意事项
- 三个值生成后连同
.env一起保存到密码管理器/安全位置;其中SYSTEM_AES_KEY丢失不可恢复。 .env用 LF 换行、UTF-8 无 BOM;从 Windows 复制内容时留意别写成 CRLF(Remote-WSL 编辑无此问题)。- 填进文件的是命令的原始输出,不要加引号以外的空格、换行或
<>占位符;
填完可用grep -E 'DB_PASSWORD|REDIS_PASSWORD|JWT_SECRET|SYSTEM_AES_KEY' .env核对四行齐全且非空。 - LLM 的 API Key 不在这里填,在网页向导里填(6.3)。
八、第五步:启动服务(待执行)
先查看配置确认无误:
cd ~/WeKnora
cat .env | grep -vE "#|^$" # 快速过一遍实际生效项8.1 官方一键脚本做什么(scripts/start_all.sh,v1.0.1)
./scripts/start_all.sh(等价 make start-all)按顺序做这些事:
.env兜底:不存在就从.env.example复制(仅检查DB_DRIVER/STORAGE_TYPE,不校验密钥);- 探测 compose:优先
docker compose(v2),回退docker-compose(v1);检查docker info引擎在运行; - Ollama 分支(仅
-o/-a时):解析OLLAMA_BASE_URL,远程地址只做连通性探测;
本地地址则检查/安装/启动 Ollama 并轮询 30 秒; - Docker 分支:检测 CPU 架构导出
PLATFORM=linux/amd64|arm64,注入前端构建号,
执行docker compose up --pull always -d(核心 5 容器;--no-pull时退化为up --build -d,
即本地源码构建); - 后台预拉
weknora-sandbox:<版本>镜像(Agent Skills 用,只拉不启动,失败只警告不阻塞); - 打印访问地址,然后
docker compose logs app docreader postgres -f前台持续跟随日志
(Ctrl+C 只退出日志,容器继续运行)。
子命令:-d 仅 Docker、-o 仅 Ollama、-s 停止(含 compose down --remove-orphans)、-c 环境诊断、-p 只拉镜像、-l 列容器、-r <服务名> 重建并重启单个容器。
⚠️ 本机不要直接无参运行(也不要
make start-all/-a):脚本把host.docker.internal归类为「本地」,随后探测的是 WSL 自己的localhost:11434
(NAT 模式下不指向 Windows 宿主),探测不通就会curl ollama.com/install.sh | sh
在 WSL 里装一套 Ollama 并systemctl restart ollama——正是 6.4
否定的方案 B:要 sudo 交互、用不上 9070 XT,还会和容器抢 16 GB 配额。
本机 Ollama 在 Windows 侧已就绪,脚本这一步纯属多余且有害。
本机用脚本的正确姿势是只走 Docker 分支:
cd ~/WeKnora
./scripts/start_all.sh -d # 等价 make start-docker;跳过 Ollama 安装/检查
# Ctrl+C 或关闭终端只退出日志,不关闭服务启动后脚本最后会前台 logs -f 跟随日志、占住当前终端——Ctrl+C 或关闭终端只退出日志,不关闭服务
(容器是以 up -d 守护方式运行的)。终端被日志占住时要关闭服务:直接按 Ctrl+C 回到提示符
再敲停止命令;或另开一个 WSL 终端执行(Docker 对同一引擎操作,任意终端均可);
想彻底避免占用,首次部署直接用 8.2 的 docker compose up -d,启动后立即返回。
# 会停止当前项目下所有由 `docker compose up` 启动的容器,并移除相关的网络、镜像和数据卷。
./scripts/start_all.sh -s # 等价 make stop-all,= docker compose down --remove-orphans
docker compose stop # 只想临时停用、保留容器实例时用down/-s 会删除容器与网络但保留命名卷(数据不丢);切勿加 -v
(down -v 会连 postgres-data/data-files/docreader-tmp 三个命名卷一起删除)。脚本 -s 中的 Ollama 停止分支
在本机无作用(WSL 未装 Ollama,自动跳过),不会影响 Windows 侧的 Ollama。
也不要加 --no-pull(会触发 --build 本地构建,本机没有 Go/Node/Rust 工具链)。
第 5 步后台预拉 sandbox 镜像本机用不到但不影响启动,介意流量/磁盘就改用下面的原生写法。
8.2 原生写法(本机主线,推荐;脚本出问题时也用它排障)
cd ~/WeKnora
docker compose pull # 本机有 daocloud 加速,约 7 GB(docreader 最大)
docker compose up -d # 启动核心 5 容器
docker compose ps # 等 app/docreader 变成 healthy与脚本的差异:不碰 Ollama、不预拉 sandbox、启动后不挂日志跟随(要看日志自己docker compose logs -f app)。行为最简单可控,本机首次部署走这条。
本机 16 GB WSL 配额下,可选组件先一律不开。确认核心稳定后再按需单独加:
docker compose --profile searxng up -d # 联网搜索
docker compose --profile neo4j up -d # 知识图谱(同时在 .env 设 NEO4J_ENABLE=true)
docker compose --profile minio up -d # 对象存储(STORAGE_TYPE 改 minio)
docker compose --profile odl-hybrid up -d # 重型文档解析(Docling 等)
# 不要在 16 GB 配额上直接 --profile full(含 clickhouse 等内存大户)可开启组件与命令
先只跑核心 5 容器,确认稳定后按下面顺序一次只加一个,每次加完用docker stats --no-stream 复核占用(各组件内存见 B)。
searxng(联网搜索,0.4–0.8 GiB,无需改.env)——最划算,优先加它:
cd ~/WeKnora
docker compose --profile searxng up -dneo4j(知识图谱 / GraphRAG,1–1.5 GiB)——先在.env设NEO4J_ENABLE=true,再启动:
docker compose --profile neo4j up -dminio(对象存储,0.3–0.5 GiB)——先在.env把STORAGE_TYPE改为minio,再启动:
docker compose --profile minio up -dlangfuse(LLM 调用链排查,2.5–4 GiB)——仅临时开,用完即收回:
docker compose --profile langfuse up -d
docker compose --profile langfuse down # 用完回收,释放 2.5–4 GiB关闭某个已开的 profile(down 只有带上同名 --profile 才会连该 profile 的容器一起停):
docker compose --profile <名> down # 如 --profile searxng down不要开:
doris(mem_limit 90% 会失控)、odl-hybrid(需本地构建,本机开不起来)、--profile full(一次拉起 12 个服务、多占 3–4 GB 磁盘,且真正危险的不在其中)。
8.3 服务清单与内存预算:当前开启与可开启
把「本机现在开着什么、还能开什么、各要多少内存」集中列在一处。数值来自
《WeKnora 架构分析和内存需求》(2026-09-27 本机实测 + 保守估算),
判据统一为:容器侧上限 15.62 GiB(即 .wslconfig 的 16 GB),以稳态为基线、解析峰值与 profile 增量做上限预留。
A. 当前开启:核心 5 容器(docker compose up -d 默认启动)
frontend——Nginx + Vue 3 静态产物,宿主80:稳态 3.2 MiB / 预热 9.6 MiB。app——Go 后端(REST / Agent / 异步 worker),宿主8080:稳态 85.9 MiB / 预热 195.1 MiB。docreader——Python gRPC 文档解析,内网50051:稳态 29.3 MiB / 预热 100.8 MiB。postgres——ParadeDB(BM25 + pgvector),内网5432:稳态 41.8 MiB / 预热 68 MiB。redis——Asynq 队列 / SSE / 限流,内网6379:稳态 4.8 MiB / 预热 6.25 MiB。- 小计:稳态 164.9 MiB(约 0.16 GiB)/ 预热 379.7 MiB(约 0.37 GiB)。
- 峰值另算:批量入库(尤其 PDF / Office)会 fork LibreOffice / pdfium 解析子进程,
这些开销不在主进程 RSS 里但计入容器,解析期按 2–3 GiB 预留(并发参数见内存需求文档第五节)。
结论:核心 5 容器平时几乎不占内存,真正要留余量的是批量解析的尖峰,不是稳态;
16 GB 配额下「只跑核心」绰绰有余。
B. 可开启:profile 可选组件(默认全不启动,按需单独拉起)
轻量档(额外 < 1 GiB,几乎不动预算):
searxng(--profile searxng):0.4–0.8 GiB。给 Agent 联网搜索能力,性价比最高,推荐先加这个。minio(--profile minio):0.3–0.5 GiB。对象存储;仅 IM 渠道要在聊天里显示图片时才需要
(STORAGE_TYPE=local+APP_EXTERNAL_URL也能解决,选它则同步把STORAGE_TYPE改为minio)。mcp(--profile mcp):0.15–0.3 GiB。内置 MCP Server。dex(--profile dex):0.03–0.06 GiB。OIDC 测试用 IdP,最轻。
中等档(1–4 GiB,加之前先确认批量解析尖峰不在进行中):
neo4j(--profile neo4j):1–1.5 GiB。知识图谱 / GraphRAG;
须同时在.env设NEO4J_ENABLE=true。weaviate(--profile weaviate):0.6–1.5 GiB。外部向量库,需切RETRIEVE_DRIVER。qdrant(--profile qdrant):起步 0.3 GiB,索引后 1–2 GiB,随向量条数近似线性增长。langfuse全套(--profile langfuse):2.5–4 GiB(langfuse-clickhouse是抖动主源)。
排查 LLM 调用链时用,用完docker compose --profile langfuse down收回。
它复用现有 postgres / redis(建langfuse库、用 redis 的 DB 1),
所以还要给核心 postgres / redis 额外留 0.2–0.4 GiB。odl-hybrid(--profile odl-hybrid):2–4 GiB。重型解析(Python + Docling),
镜像仅本地构建、不发布到 Docker Hub,本机没有工具链,实际也开不起来。milvusstandalone(--profile milvus):2–4 GiB。外部向量库,官方建议配置更高,轻负载余量不大。
不建议开启:
doris(--profile doris):1.5 GiB 起、实际可达 8 GiB 以上;且 BE 的mem_limit默认 90%,
按宿主可用内存计算,在 15.62 GiB 的池子里它会认为自己有权用掉约 14 GiB——
不是「多占 8 GB」,而是「随时可能吃掉整个配额」。本机不要开。sandbox(在--profile full内):不是常驻服务,command: ["true"]、restart: "no",
启动即退出,只保证 722 MB 镜像被拉起;真正的沙箱容器按会话动态创建,本机默认关闭。
C. full profile 说明(与官方架构页不同,以本机 compose 为准)
--profile full会拉起:sandbox、searxng、minio、neo4j、qdrant、dex、langfuse-*(clickhouse / minio / worker / web / db-init)、mcp——合计常驻约 6–7 GiB。- 它不包含
milvus、weaviate、doris、odl-hybrid——这四个只有各自的同名 profile,
不会因开full被顺带拉起;真正危险的那几个反而不在full里。 - 因此
full在 15.2 GiB 余额内其实放得下,但它会一次性拉起 12 个服务、多占 3–4 GB 磁盘,
并引入一堆本机用不到的东西;推荐仍按 B 的顺序逐个加,而非一把full。
上述为「稳态 + 保守上限」。切到任一 profile 后建议用
docker stats --no-stream
复核实际占用;数值口径、估算依据与 profile 归属详见《WeKnora 架构分析和内存需求》。
九、验证部署是否成功(含初始化向导)
命令行自检(WSL 里):
docker compose ps # 全部 running/healthy
curl http://localhost:8080/health # 期望 {"status":"ok"}
curl http://<WSL网关IP>:11434/api/version # Windows Ollama 可达(网关 IP 以实测为准)
# 再验证最后一跳「容器 → host.docker.internal → Windows Ollama」(app 镜像未必有 curl,wget/getent 更稳)
docker compose exec app getent hosts host.docker.internal
docker compose exec app sh -c "wget -qO- http://host.docker.internal:11434/api/version || curl -s http://host.docker.internal:11434/api/version"
# 返回 Ollama 版本 JSON,说明容器到模型服务全链路通浏览器(Windows 侧)打开:
- 前端:
http://localhost(端口保持默认 80) - API 直连:
http://localhost:8080 - 若
localhost不通:hostname -I查 WSL IP 后访问http://<WSL_IP>:80
安全提示:compose 发布的 80/8080 绑定在 Windows 的所有网卡上,同一局域网的人也能打开你的
WeKnora——而第一个注册的账号就是管理员。可信家庭网络无碍;在不可信网络(公司/公共 Wi-Fi)下,
先用 Windows 防火墙限制 80/8080 入站,或第一时间完成管理员注册。
标准版首次访问是注册页(与 Lite 的免注册不同),注册第一个账号即管理员。随后按向导走完才算跑通:
- 新建知识库,类型选
document。 - 初始化向导里选模型(本机推荐组合):
- Embedding(向量模型):选 Ollama / OpenAI 兼容本地源,Base URL 填
http://host.docker.internal:11434(若向导只让填模型名,就填bge-m3,地址已在.env里)。 - LLM(对话模型):选 OpenAI 兼容 provider,填远端 API 的 Base URL / Key / 模型名(6.3)。
- 重排(Rerank)、图片理解(VLM)先不开。
- Embedding(向量模型):选 Ollama / OpenAI 兼容本地源,Base URL 填
- 上传一篇文档,进文档详情看解析追踪,等状态变为完成。
- 在知识库提问,确认答案带出处引用。
向导里如果「测试连接」失败,先看第十三节。
十、Windows 与 WSL2 互通要点(本机配置)
- 文件互访:
- Windows 资源管理器地址栏输入
\\wsl$\Ubuntu-24.04\home\<WSL用户名>\直达 WSL 家目录。 - WSL 访问 Windows 盘符:
/mnt/c、/mnt/e、/mnt/m,仅用于临时拷贝。
- Windows 资源管理器地址栏输入
- 性能红线:仓库与配置留在 WSL 的 ext4 文件系统(
~/WeKnora,不要放/mnt/*);
容器的命名卷由 Docker 管在数据盘 VHDX 里(见 11.1),
两者都不在 9P 挂载盘上。/mnt/*走 9P 协议只适合临时拷源码/文件,数据库放上去会有锁和性能问题。 - 资源配额:本机
C:\Users\<Windows用户名>\.wslconfig已配 16 GB / 8 核 / 8 GB swap,autoMemoryReclaim=gradual+sparseVhd=true已开(自动回收内存、VHD 稀疏化)。
改该文件后需wsl --shutdown再重开 Ubuntu 生效。
若日后同时跑多个 profile 导致 OOM,可把memory提到 24GB(宿主共 64GB,留够 Windows+Ollama)。 - 容器 → Windows Ollama:优先
host.docker.internal;解析失败时用网关 IP
(ip route show default,当前<WSL网关IP>,每次wsl --shutdown后可能变)。 - 网络模式前提:本文所有网络写法基于 WSL2 默认 NAT 模式。若日后在
.wslconfig
开了networkingMode=mirrored,网关 IP 取法和 localhost 行为都会变
(host.docker.internal由 Docker Desktop 维护仍可用,「网关 IP 访问宿主」的备用法要换思路)。 - 防火墙:已在 6.1 给出 11434 入站规则。
- Docker 数据位置:镜像、容器与命名卷的物理位置、卷清单、备份恢复与空间回收统一见
第十一节。
十一、Docker 数据盘、命名卷与备份恢复
本节集中说明四类原来散落在各节的内容:数据实际存在哪个物理文件、WeKnora 用了哪些命名卷、
怎么做备份与还原、磁盘空间怎么回收。
11.1 物理布局:所有容器数据都在两个 VHDX 里
Docker Desktop(WSL2 后端)的引擎跑在独立的 docker-desktop 发行版中,不在 Ubuntu-24.04 里。docker info 显示的引擎内根目录是 /var/lib/docker(overlayfs + containerd 快照器),
它物理上映射为 Windows 侧 M 盘上的 VHDX 虚拟磁盘(2026-09-26 实测):
M:\Docker\wsl\DockerDesktopWSL\disk\docker_data.vhdx(实测约 5.6 GB,拉取 WeKnora
约 7 GB 镜像后预计增至 13 GB 左右)——镜像层、容器可写层、全部命名卷数据都在这一个文件里,
资源管理器看不到散文件,只能经 Docker 命令或下面的备份方法访问。M:\Docker\wsl\DockerDesktopWSL\main\ext4.vhdx(实测约 0.09 GB)——docker-desktop
发行版的系统盘,不放业务数据。- 与之并列但用途不同的第三个盘:Ubuntu-24.04 自己的 ext4.vhdx,装的是仓库与
.env
(~/WeKnora),不要和数据盘混淆。
由此得到两条直接结论:
- 不要去 Ubuntu 里找卷数据:
/var/lib/docker/volumes在 Ubuntu-24.04 中是空的或不存在,
网上常见的sudo tar czf ... /var/lib/docker/volumes打出来的是空包。 - VHDX 只增不减:实例内删镜像、删文件,Windows 侧 VHDX 不会自动缩小(空间回收见 11.4)。
概念辨析:数据卷 ≈ 硬盘逻辑分区吗?
只能算「形似」,更准确的说法是:Docker 卷 ≈ 一块由 Docker 托管、挂载进容器的专用目录。
- 形似点:卷独立于容器存在(容器删了卷还在);都要挂载后才能用;命名卷像分了盘符的分区,匿名卷像系统自动分配盘符。
- 关键差异:分区有分区表和固定空间边界(C 盘满不影响 D 盘)、自带独立文件系统;卷在 VHDX 内物理上只是 ext4 上的普通目录,各卷共享整块 VHDX 空间、没有配额边界,一个卷写满就是整块盘满;卷本身也不再格式化。
- 层级对应:VHDX 才最接近「硬盘/分区」这一层;卷的挂载机制更接近 Linux bind mount。容器的「身体」(镜像层 + 可写层)在
overlay2/,卷在volumes/,二者平级且都在同一个 VHDX 内——容器不是装在卷里的。
物理归属(2026-09-27 实测):
客户端 / 引擎分离:为什么在 Ubuntu 终端 docker images 看得到镜像,但镜像不在 Ubuntu 里
Docker 是 C/S 架构:docker 命令只是客户端(CLI),真正存镜像、跑容器的是守护进程 dockerd(引擎)。
本机这两个角色分处两个 WSL 发行版,在 Ubuntu 终端看到列表只是「CLI 向远端引擎查询后打印结果」,
与"用 mysql 客户端连远程数据库执行 show tables;,表并不在客户端机器上"同理。2026-09-28 实测四条证据:
- Ubuntu 里的 docker 是 Docker Desktop 注入的软链,不是本机安装的守护进程:
readlink -f $(which docker)→/mnt/wsl/docker-desktop/cli-tools/usr/bin/docker。 - CLI 经 WSL Integration 架的 socket 转发请求(
docker context ls显示unix:///var/run/docker.sock),对端是 docker-desktop 发行版,不是 Ubuntu。 - 引擎自报身份:
docker info -f '{{.Name}} {{.DockerRootDir}}'→docker-desktop /var/lib/docker。 - Ubuntu 本地没有数据目录:
ls /var/lib/docker→No such file or directory。
因此 docker images 列出的约 11.4 GB 镜像(含 5.69 GB 的 docreader)一直在 docker_data.vhdx 的overlay2/ 里、由 Docker Desktop 统一管理;Ubuntu 的 ext4.vhdx 只装仓库与 .env,不含任何镜像/卷数据。
多个 WSL 发行版与 Windows 侧 CLI 连的是同一个引擎,镜像全局只存一份。docker images 的 EXTRA 列U(In Use)表示该镜像有容器正在使用,与存放位置无关。
自行复核三条命令(均在 Ubuntu 终端执行):
readlink -f $(which docker) # CLI 实体在 /mnt/wsl/docker-desktop/ 下,不是 Ubuntu 自己的
docker info -f '{{.Name}}' # 引擎名 docker-desktop
ls /var/lib/docker # Ubuntu 本地:No such file or directory11.2 卷清单与数据落位(v0.8.2,2026-09-27 docker inspect 实测)
核心 5 容器实际创建三个命名卷(实测前缀为小写 weknora_,即下面备份命令grep -i weknora 能命中的原因;2026-09-26 初次记录时误写为 WeKnora_ 大写前缀并漏列第三个):
weknora_postgres-data(compose 逻辑名postgres-data,实测 176 MB):挂载到 postgres/var/lib/postgresql/data——知识库、文档分块、向量与 BM25 索引、系统配置、用户/会话全部在这个 ParadeDB 库里,最核心。weknora_data-files(逻辑名data-files,实测 2 MB):挂载到 app/data/files
(LOCAL_STORAGE_BASE_DIR默认值)——STORAGE_TYPE=local时上传的原始文档与附件,按租户分目录(实测/10000/<uuid>/)。weknora_docreader-tmp(逻辑名docreader-tmp,实测仅 4 KB):docreader 以 RW 挂/tmp/docreader,app 以只读挂同一路径共享——解析中间图片,用完即清的可重建缓存,不是关键数据。
另有一个匿名卷(不带 weknora 前缀,grep 不到,容易遗漏):redis 镜像自带 VOLUME /data,
而 compose 的 redis 服务未声明命名卷,Docker 自动创建匿名卷(实测 c2cd25936bde…,43.5 MB,
内含 appendonlydir/ + dump.rdb)。里面是 Asynq 队列、SSE、限流等运行态数据:stop/restart/up 复用容器时保留;docker compose down 再 up 会生成新匿名卷、Redis 从零开始
(不影响已入库内容,但排队中的任务会丢)。备份方式一不覆盖它,属正常——它不是业务数据。
物理位置:这些卷与容器可写层全部在 docker-desktop 发行版的/var/lib/docker/volumes/<卷名>/_data,即 Windows 侧M:\Docker\wsl\DockerDesktopWSL\disk\docker_data.vhdx(见 11.1);Ubuntu 里没有对应目录,
Windows 侧也没有业务数据的本地映射文件夹。唯一的 bind mount 是 WSL 仓库内的./config/config.yaml → app /app/config/config.yaml;.env 不挂载,由 compose 注入环境变量。
可选 profile 才会额外创建:minio_data(minio)、neo4j-data(知识图谱)、qdrant/milvus/
weaviate/doris 各自的卷、langfuse_* 等。本机不开这些 profile 就不创建。
查看实际卷:docker volume ls | grep -i weknora(匿名卷需 docker volume ls 不带过滤才能看到)。
五个容器 ↔ 卷的挂载关系(2026-09-27 docker inspect 实测;容器可写层在 overlay2,不属于任何卷):
逐容器说明:
- frontend:0 个卷、0 个 bind mount,纯静态产物 + NGINX,无状态,删容器重建什么都不丢。
- app:
data-files读写;docreader-tmp只读(消费 docreader 产出的图片);另有唯一一个不在数据盘 VHDX 内的挂载——Ubuntu 仓库里的config/config.yaml(bind mount)。 - docreader:
docreader-tmp读写(它是生产者),内容为临时图片,可随时清空。 - postgres:独占
postgres-data,最核心、不可丢。 - redis:独占匿名卷,
down再up后换新卷、从零开始(见上文匿名卷说明)。
生命周期对照(操作命令详见 8.1 / 11.4):
docker compose stop:容器停,可写层与卷都不动。docker compose down:删 5 个容器 + 网络(可写层清除),3 个命名卷保留;redis 匿名卷脱离引用成为孤儿,内容暂留 VHDX 等 prune。docker compose down -v:连 3 个命名卷目录一起删除——知识库与上传文件全没,绝对慎用。- 卷之间无空间隔离:任一卷暴涨消耗的都是同一个 VHDX 容量,盘满影响全部容器。
11.3 备份与还原(升级前务必做)
本节内容已并入配套文档《WeKnora 部署与运维》的「备份与恢复」节(本博客未收录该文档),此处不再重复:
备份文件落盘位置、三种方式、卷级还原、.env一并备份等要点均以该节为准。
11.4 磁盘空间回收
VHDX 只增不减,按代价从小到大:
docker image prune -f(升级后清旧镜像层)、必要时docker system prune先看docker system df确认可回收量;- 本机
.wslconfig已开sparseVhd=true,空闲块会自动稀疏化; - 仍不下降再手动 compact:Docker Desktop → Resources → Advanced 中对数据盘 compact,
或wsl --shutdown后用Optimize-VHD -Mode Full(需 Hyper-V 模块)处理M:\Docker\wsl\DockerDesktopWSL\disk\docker_data.vhdx。
危险操作提醒:
docker compose down -v会连命名卷一起删除,绝对慎用;docker volume prune会删所有未被容器引用的卷,执行前先docker volume ls看清。
十二、日常运维
cd ~/WeKnora
# 状态与日志
docker compose ps
docker compose logs --tail=200 app
docker compose logs --tail=200 docreader
docker compose logs -f app
# 停止 / 重启
docker compose down # 注意:down -v 会连数据卷一起删,绝对慎用(见 11.4)
docker compose restart app
# 改了 .env 后必须重建对应容器(restart 不会重载环境变量)
docker compose up -d app升级:
# 1) 先备份(见 11.3)
# 2) 仓库切到新 tag:git fetch --tags && git checkout v0.8.3(目标 tag 以 Releases 页为准)
# 3) 编辑 .env:WEKNORA_VERSION 同步改成同一个 tag(仓库 tag 与镜像 tag 必须一致)
# 并对照新 tag 的 .env.example 检查是否有新增变量
docker compose pull
docker compose up -d
docker image prune -f # 清理升级后留下的旧镜像层(空间回收见 11.4)数据库迁移由 AUTO_MIGRATE=true 启动时自动执行(AUTO_RECOVER_DIRTY=true 兜底脏状态);
升级后到「设置 → 系统信息」确认迁移版本与依赖连接无报错。
Windows 重启 / wsl --shutdown / 睡眠唤醒后的恢复顺序:
- 确认 Docker Desktop 已 Running(建议在 Docker Desktop 设置里勾选 Start Docker Desktop when you sign in)。
cd ~/WeKnora && docker compose up -d——幂等操作:已在跑的容器不动,没起的拉起来。docker compose ps全部 healthy 后再用。- Ollama 模型被卸载属正常,首次请求会重新加载;想让
bge-m3常驻可设用户变量OLLAMA_KEEP_ALIVE=24h(重启 Ollama 生效)。
十三、常见问题排查(含 AMD 显卡专节)
13.1 AMD 9070 XT + Ollama Vulkan 排障
本机现状:9070 XT(gfx1200)被 Ollama 0.34.2 经 Vulkan 后端识别;bge-m3 100% GPU 正常;8B/9B 对话模型加载报 Vulkan OOM:
llama-server reported out-of-memory during startup:
alloc_tensor_range: failed to allocate Vulkan0 buffer of size 1073741824
ggml_vulkan: Failed to allocate pinned memory (vk::Device::allocateMemory: ErrorOutOfDeviceMemory)按以下顺序尝试(每改一项都退出托盘 Ollama 再重启):
- 更新 AMD 驱动:RDNA4 很新,装最新版 AMD Adrenalin(本机当前 32.0.31041.1004),装完重启 Windows。
- 去掉 HIP 设备覆盖:日志里有
user overrode visible devices HIP_VISIBLE_DEVICES=1警告。
在系统属性 → 环境变量里删除HIP_VISIBLE_DEVICES(用户级和系统级都查),重启 Ollama,
再看%LOCALAPPDATA%\Ollama\server.log是否改走 ROCm/HIP(gfx1200 已在官方支持列表)。 - 关掉占显存的程序:游戏、其他浏览器硬件加速重页面、录屏/串流软件;任务管理器 → GPU 看显存占用。
- 换更小的模型验证:
ollama pull qwen2.5:3b后ollama run,小模型能起说明是大块连续显存分配问题。 - 临时强制 CPU(救急用,慢):设用户变量
OLLAMA_NUM_GPU=0(该变量控制 offload 到 GPU 的层数,0 = 纯 CPU),重启 Ollama;
7700 跑 8B 约每秒几 token,可用于功能验证,不适合日常。排障完记得删掉这个变量再重启 Ollama。 - 更新/回退 Ollama 版本:Vulkan 后端较新,关注 Ollama release notes 对 RDNA4 的修复。
验证 GPU 是否真的在工作:
ollama run qwen3.5:9b "用一句话介绍你自己"
ollama ps
# PROCESSOR 列:100% GPU 才是显卡推理;100% CPU 或部分 offload 都不对排查期 LLM 直接用远端 API,不阻塞 WeKnora 部署。
13.2 向导里看不到 Ollama / 向量模型调用失败
- 确认 Ollama 进程在跑:Windows PowerShell
ollama list,且Test-NetConnection 127.0.0.1 -Port 11434为 True。 - 确认已设
OLLAMA_HOST=0.0.0.0:11434并重启过 Ollama(只监听 127.0.0.1 时容器必连不上,本机踩中)。
注意Test-NetConnection 127.0.0.1通不代表监听地址改对了;以netstat -ano | findstr :11434
显示0.0.0.0:11434为准,没变就是 6.1 那个会话继承坑。 - WSL 里
curl http://<网关IP>:11434/api/version要通;不通检查防火墙 11434 入站规则;
规则已加仍不通时,查第三方安全软件(360、火绒等)自带的防火墙是否另有一层拦截。 - 向导/
.env地址用http://host.docker.internal:11434,不要写127.0.0.1(那是容器自己)。 - 模型名严格写
bge-m3(ollama list显示什么就填什么,注意带不带:latest)。
13.3 其他常见项
git clone报Could not resolve host: github.com(本机踩中,已修复):WSL 能 ping 通 IP
(ping 223.5.5.5正常)但域名全解析失败——/etc/resolv.conf里自动生成的nameserver 10.255.255.254(WSL NAT DNS 代理)在本机网络下不响应。修复(WSL 终端执行,
sudo 会提示输密码;或在 Windows PowerShell 用wsl -d Ubuntu-24.04 -u root免密进入后执行):printf '\n[network]\ngenerateResolvConf=false\n' | sudo tee -a /etc/wsl.conf sudo rm -f /etc/resolv.conf printf 'nameserver 223.5.5.5\nnameserver 119.29.29.29\n' | sudo tee /etc/resolv.conf然后在 Windows PowerShell 执行
wsl --shutdown,等约 8 秒重开 Ubuntu,验证:getent hosts github.com应返回140.82.x.x(GitHub 真实段),curl -sI https://github.com应返回HTTP/2 200。
注意本机网络存在部分域名 DNS 劫持(如codeload.github.com曾返回非 GitHub 的172.182.252.x),但 git clone 的 smart HTTP 数据走github.com,实测不受影响,无需处理。
另外命令里的 URL 不要带 Markdown 反引号,直接写https://github.com/Tencent/WeKnora.git。docker: command not found(WSL 里):先看是不是引擎根本没运行——wsl --shutdown或 Windows 重启后 docker-desktop 发行版是 Stopped,症状与「没开 WSL Integration」
完全一样。判别顺序:Windows PowerShell 跑docker version,能出版本号说明引擎正常,
再去 Docker Desktop → Resources → WSL Integration 检查 Ubuntu-24.04 开关;docker version连不上 npipe 就先启动 Docker Desktop(本机路径见 13.4)。前端打不开 / 端口被占:
netstat -ano | findstr :80、:8080;被占就改.env的FRONTEND_PORT/APP_PORT后docker compose up -d(本机当前两端口空闲)。
若占用方 PID 是 4(System),那是 Windows 的 HTTP.sys(IIS、SQL Server Reporting Services 等系统组件),
进程杀不掉,需停对应系统服务(如net stop http需先停依赖,谨慎),或直接给 WeKnora 换端口更省事。容器反复重启 / OOM:
docker compose logs app看是否内存不足;wsl --shutdown后按第十节调大.wslconfig的 memory;不要开fullprofile。上传失败或解析一直处理中:文档详情里看失败原因;
docker compose ps确认 docreader healthy;确认数据卷没放在/mnt/c。页面版本和预期不一致:
docker compose up -d会复用本地缓存镜像,先docker compose pull;注意WEKNORA_VERSION的 tag 要带v前缀。迁移失败 / dirty:
AUTO_RECOVER_DIRTY默认开;修不了磁盘满、扩展缺失等根因,先看 app 启动日志、备份后处理,不要删数据卷跳错误。Ollama 云模型 402:
*-cloud模型需要 ollama.com 订阅或充值,未付费时直接忽略,用本地 bge-m3 + 远端 LLM。拉镜像慢:本机已配 daocloud 加速;若仍失败可换网络重试,
docker compose pull支持断点续拉。问答结束后 granite4.1:8b 仍被反复调用(2026-09-27 实测,本机案例):
- 现象:对话已结束,
ollama ps仍显示 granite4.1:8b 常驻且不断刷新 UNTIL;模型以 131072 上下文、约 27 GB 加载,PROCESSOR为 48%/52% CPU/GPU(装不进 16 GB 显存的层落到 CPU),server.log中单次/api/chat耗时约 1m36s–1m40s。 - 根因:该知识库(62 篇 md 批量入库)开启了问题生成(
question_generation_config.enabled=true, question_count=3)与文档摘要(summary_enabled=true)。文档解析完成后,Asynq 队列异步为每个分块生成问题(app 日志purpose=question_generation, model=granite4.1:8b,10 分钟内 159 次)、为每篇文档生成摘要(purpose=document_summary, model=gemma4:31b-cloud)——与问答会话无关;叠加 Ollama 默认keep_alive=5m驻留,任务持续时模型永不卸载。 - 关键行为:在界面关闭「问题生成」只阻止新任务入队,队列中的存量任务仍会继续(实测关闭后 18 秒仍有 granite 调用)。
- 处置:① 等存量任务消化完,模型驻留 5 分钟后自动卸载;② 立即释放用 Windows 侧
ollama stop granite4.1:8b(正在执行的任务失败,Asynq 有限重试后放弃);③ 系统管理员在「设置 → 任务队列」取消排队任务最干净;④ 本机半 CPU 8B 不适合批量后处理,问题生成/摘要也应配远端 OpenAI 兼容 API(同日实测云端摘要每篇仅 3–6 秒);⑤ 只想缩短空闲驻留,设 Windows 用户变量OLLAMA_KEEP_ALIVE=1m(或0用完即卸载,代价是下次重新加载 27 GB 很慢),重启 Ollama 生效。 - 排查命令:
docker compose logs app --since 10m | grep "purpose="(看调用类型与模型);Select-String "$env:LOCALAPPDATA\Ollama\server.log" -Pattern "POST .*/api/(chat|generate)" | Select -Last 15(看请求时间线与耗时)。
- 现象:对话已结束,
13.4 WSL 交互弯路与标准姿势(本机实操记录)
2026-09-25/26 部署过程中与 WSL 交互实际踩到的坑,按发生顺序记录。每条给出
「现象 → 容易误判的方向 → 真实根因 → 正确做法」。
13.4.1 手工操作踩过的坑
坑 1:在
/mnt/c目录里执行克隆- 现象:提示符是
<WSL用户名>@<主机名>:/mnt/c/Users/<Windows用户名>$就直接敲git clone。 - 根因:从 PowerShell 进 WSL 默认继承 Windows 当前目录,不是家目录;即使克隆成功,
仓库也落在 9P 挂载盘上,后面数据库卷会踩性能/锁的坑。 - 正确:任何仓库操作前先
cd ~(或cd ~/WeKnora),用pwd确认输出/home/<WSL用户名>。
- 现象:提示符是
坑 2:命令 URL 带了 Markdown 反引号
- 现象:
fatal: unable to access 'https://github.com/...`'`,反引号成了 URL 的一部分。 - 根因:从 Markdown 文档复制命令时把行内代码标记一起复制了。
- 正确:用代码块右上角的复制按钮,或只复制纯文本;粘贴后先扫一眼首尾有没有
`。
- 现象:
坑 3:
Could not resolve host: github.com误以为是 GitHub 被墙- 容易误判:配 git 代理、换 GitHub 镜像、反复重试 clone——本机 Windows 侧无代理且
Test-NetConnection github.com -Port 443为 True,根本不是被墙。 - 判别方法(30 秒定位 DNS 还是连通性):
ping -c 2 223.5.5.5通而getent hosts github.com失败 ⇒ DNS 问题;
ping IP 也不通 ⇒ 才是网络/代理问题。 - 根因:WSL 自动生成的
nameserver 10.255.255.254(NAT DNS 代理)在本机网络下不响应。 - 正确修复:见 13.3 第一条(固定
223.5.5.5/119.29.29.29),无需代理。
- 容易误判:配 git 代理、换 GitHub 镜像、反复重试 clone——本机 Windows 侧无代理且
坑 4:修系统文件时 sudo 卡在密码输入
- 根因:非交互式会话里
sudo要密码,脚本会挂住或失败。 - 正确:需要 root 的一次性操作,在 Windows PowerShell 用
wsl -d Ubuntu-24.04 -u root -- bash -c "<命令>"直接进入免密 root 会话执行;
日常操作仍用普通用户。
- 根因:非交互式会话里
坑 5:
wsl --shutdown之后 WSL 里docker命令消失- 现象:修 DNS 重启 WSL 后,
docker: command not found。 - 容易误判:WSL Integration 开关掉了,去翻 Docker Desktop 设置。
- 根因:
wsl --shutdown会把 docker-desktop 发行版和 Docker Desktop 引擎一起停掉;
引擎不运行时集成开关再开着也没用,症状与 integration 未开完全相同。 - 正确:先在 Windows 侧启动 Docker Desktop,轮询
docker version能出版本号
(引擎启动约需 30–90 秒),再回 WSL 操作。本机 Docker Desktop 不在默认安装路径:
实际是C:\Users\<Windows用户名>\AppData\Local\Programs\DockerDesktop\Docker Desktop.exe
(C:\Program Files\Docker\...在本机不存在,照网上路径启动会报"系统找不到指定的文件")。
- 现象:修 DNS 重启 WSL 后,
坑 6:改
.env的复合脚本静默失败,还以为写进去了- 现象:一串
sed/awk脚本退出码非 0,但部分输出看似正常;实际.env原封未动。 - 根因:PowerShell →
wsl -- bash -lc "..."嵌套执行时,外层 PowerShell 会先吃掉
双引号里的$变量,反斜杠转义被层层改写,set -e使脚本在第一条坏掉的语句处退出。 - 正确:见 13.4.2 的两种姿势。任何"写配置"操作后必须 grep 回读验证,不能只看退出提示。
- 现象:一串
13.4.2 从 Windows 侧操作 WSL 的标准姿势
姿势 A:单条简单命令——用单引号包住 bash 脚本(PowerShell 单引号不展开 $):
wsl -d Ubuntu-24.04 -u <WSL用户名> -- bash -lc 'cd ~/WeKnora && grep "^DB_PASSWORD=" .env'姿势 B:多行/含循环/含 $ 的复杂脚本——用 base64 通道,彻底绕开两层引号转义:
# PowerShell 端:脚本写 here-string,转成 LF 后 base64
$script = @'
cd ~/WeKnora || exit 1
while IFS="=" read -r k v; do
printf "%s length=%s\n" "$k" "${#v}"
done < <(grep -E "^(DB_PASSWORD|REDIS_PASSWORD)=" .env)
'@
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(($script -replace "`r`n","`n")))
wsl -d Ubuntu-24.04 -u <WSL用户名> -- bash -c "echo $b64 | base64 -d | bash"注意 PowerShell 的 here-string 默认是 CRLF,直接管道给 bash 会出现诡异的: No such file or directory(\r 被当成命令的一部分);上面的 -replace 换行 + base64
同时解决了 CRLF 和引号两个问题。
姿势 C:操作前的三秒检查清单(手工执行同样适用):
pwd——在/home/<WSL用户名>而不是/mnt/c|e|m/...;- 要用 docker 时,Windows 侧
docker version能出版本号(引擎在运行); - 改完网络/
.wslconfig类配置若执行了wsl --shutdown,收尾动作顺序是:
重开 Ubuntu → 启动 Docker Desktop → 等引擎就绪 → 再继续 docker 操作。
姿势 D:让 AI/自动化工具执行时的两个已知限制:
- 在 Trae 沙箱内
Start-Process启动 Docker Desktop,进程会立刻退出;需在沙箱外启动
(本次由用户授权后执行)。同理沙箱内访问非工作盘符(如 MemPalace 数据库所在盘)
会被拒绝,报disk I/O error,并非数据库损坏。 - 自动化写入凭据类文件会触发安全确认,属正常拦截;确认后才会真正落盘。
十四、附录:Lite 单二进制在 WSL2 的简版步骤(无 Docker)
Lite 版官方只发布 Linux/macOS 产物,Windows 上只能在 WSL2 里跑。适合临时验证、低资源场景;
代价是无共享空间/多空间协作、解析引擎只有内置 Simple、默认仅本机访问。
下载:到 https://github.com/Tencent/WeKnora/releases 找 Lite 专用 tag 下的WeKnora-lite_<版本>_linux_amd64.tar.gz(注意:主版本 tag 如 v0.8.0 本身不含二进制资产),
浏览器下载后拷进 WSL 家目录,或 WSL 里 curl -fLO <资产URL>。
端口提醒:Lite 默认也是 8080,与标准版 APP_PORT 冲突,两者不要同时跑。
# 1) 解包到 WSL 本地文件系统(不要放 /mnt/c)
tar xzf WeKnora-lite_<版本>_linux_amd64.tar.gz
cd WeKnora-lite_<版本>_linux_amd64
# 2) 配置
cp .env.lite.example .env.lite
# 必改:DB_PATH、LOCAL_STORAGE_BASE_DIR、SERVER_PORT、SYSTEM_AES_KEY、JWT_SECRET
# 保持:DB_DRIVER=sqlite、RETRIEVE_DRIVER=sqlite、STORAGE_TYPE=local、STREAM_MANAGER_TYPE=memory
# 3) 模型:不用在 WSL 里装 Ollama(WSL 用不上 9070 XT)。
# 先按第 6.1 节开放 Windows 的 Ollama 监听,然后把地址指向 WSL 网关:
# OLLAMA_BASE_URL=http://<WSL网关IP>:11434 (IP 以 ip route 实测为准)
# 向量模型 bge-m3 已在 Windows 侧就绪可直接复用。
# 4) 启动(先前台跑一次验证)
set -a && source .env.lite && set +a
./WeKnora-lite
# 5) 验证
curl http://127.0.0.1:8080/health # 期望 {"status":"ok"}
# 浏览器打开 http://localhost:8080,Lite 免注册,直接进入十五、本机实值速查表(替代通用占位符)
- WSL 发行版:
Ubuntu-24.04(默认,WSL2) - WSL 用户名:
<WSL用户名> - Windows 用户目录:
C:\Users\<Windows用户名> - WSL 仓库路径:
/home/<WSL用户名>/WeKnora(v0.8.2 已克隆,detached HEAD;.env已按 7.2 生成并写入,值以占位符给出,模板备份为.env.template-defaults.bak) - WSL DNS:
223.5.5.5/119.29.29.29(已写入/etc/resolv.conf,generateResolvConf=false) - Windows 访问 WSL:
\\wsl$\Ubuntu-24.04\home\<WSL用户名>\ - WSL 网关 IP(容器/Lite 访问 Windows Ollama 的备用地址):当前
<WSL网关IP>,重启后以ip route show default实测为准 - 容器访问 Ollama 的固定地址:
http://host.docker.internal:11434 - Ollama 版本 / 路径:0.34.2 /
C:\Users\<Windows用户名>\AppData\Local\Programs\Ollama\ollama.exe - Ollama 日志:
C:\Users\<Windows用户名>\AppData\Local\Ollama\server.log - 向量模型:
bge-m3(1024 维,已验证 100% GPU) - 本地 LLM(待修复):
qwen3.5:9b、granite4.1:8b - LLM 推荐路线:远端 OpenAI 兼容 API(Key 在网页向导填,不进
.env) - 前端 / 后端端口:
80/8080(当前空闲,保持默认) WEKNORA_VERSION:v0.8.2(与仓库 git tag 一致);追稳定版可写latest,开发版写main- Docker:Engine 29.8.0 / Compose v2 5.5.1;数据盘
M:\Docker\wsl\DockerDesktopWSL\disk\docker_data.vhdx(镜像/卷都在此,详见第十一节);mirrorhttps://docker.m.daocloud.io/ - WSL 配额:16 GB 内存 / 8 核 / 8 GB swap(配置文件
C:\Users\<Windows用户名>\.wslconfig) - 硬件:Ryzen 7 7700(8C16T)/ 64 GB / Radeon RX 9070 XT 16 GB(驱动 32.0.31041.1004)