WSL2 + Docker + Harbor 评测框架:从 0 到 Oracle 自测 100% 通过,避坑全记录(2026 最新)
本文基于 Harbor 评测框架 0.23.0、WSL2 Ubuntu、Python 3.14、Docker Desktop,记录了从 Windows 原生到 WSL2 的完整踩坑与修复过程。照着操作,可避开 90% 以上的常见报错,顺利拿到 reward: 1.0。
前言
不少开发者在本地搭建 Harbor 评测环境时,极易撞上 Windows 与 WSL2 跨系统路径兼容异常、Docker 与 Harbor 部署顺序冲突、异步事件循环报错、Docker build context 越界、verifier 网络下载失败 这几类高频问题。我在深圳本地的 Windows 环境下踩完了所有相关坑点,整理出这套完整可复现的落地步骤。本文适配有一定 Docker 基础、希望在本地快速搭建 Harbor 评测框架的开发者,看完就能避开 90% 以上的常见报错,顺利启动第一条 Oracle 自测任务并拿到满分。
一、环境说明与整体依赖关系
组件 版本/说明
宿主机 Windows 10/11
子系统 WSL2 + Ubuntu
容器 Docker Desktop(启用 WSL2 集成)
Harbor 评测框架 0.23.0(通过 uv tool install harbor 安装)
Python 3.14(WSL2 内)
任务目录 ~/projects/myapp001/exam_002
核心依赖链:Windows → WSL2 → Docker Desktop → Harbor 评测框架 → 任务容器。
二、关于 Harbor 镜像仓库的部署顺序(与评测框架无关)
很多人一开始就搞错了部署顺序:先解压 Harbor 镜像仓库离线包执行部署,之后才发现系统里还没装 Docker,误以为之前操作作废。实际上完全没必要重装。
Harbor 镜像仓库的所有组件本身就以容器形式打包,先部署后装 Docker,只是当时缺少底层运行环境,所有配置项、已上传镜像、用户权限、项目数据都完整保存在持久化目录中。只需三步唤醒:
- 确认 Docker Desktop 已正常启动,WSL2 与 Docker 互通正常。
- 进入此前解压的 Harbor 离线安装包目录,执行 docker-compose up -d,等待 1~2 分钟。
- 访问 Harbor Web 管理地址,确认原有项目、镜像数据完整。
⚠️ 注意:本文后续讨论的 Harbor 评测框架(harbor trials start)与 Harbor 镜像仓库(CNCF Harbor)是两个不同的东西,请勿混淆。
三、WSL2 跨 Windows 项目路径:再也不迷路
在 WSL2 中编写项目,转头在 Windows 终端就找不到路径?核心是没理清两个系统的路径映射。
Windows 资源管理器地址栏输入:(通过\wsl$根目录寻址)
bash
\\wsl.localhost\Ubuntu\home\administrator\projects\myapp001
WSL 子系统内绝对路径:
bash
/home/administrator/projects/myapp001
两边文件实时同步。快速定位技巧:在 WSL 终端执行 explorer.exe .,自动唤起 Windows 资源管理器并定位到当前目录。
⚠️ 避坑:不要在 Windows 里直接修改 WSL 子系统内的文件权限,否则后续执行 shell 脚本大概率触发权限不足。
四、避坑 1:Windows 原生 PowerShell 下 Harbor 异步报错
- 报错现象:
bash
RuntimeError: asyncio.run() cannot be called from a running event loop
或 ProactorEventLoop 相关 TypeError。
-
原因:Harbor 在 Windows 原生环境下使用 asyncio.run(coro, loop_factory=asyncio.ProactorEventLoop),Python 3.13/3.14 对此兼容性不佳。
-
解决方案:
首选:直接使用 WSL2,彻底规避 Windows asyncio 子进程兼容问题。
备选:修改 Harbor 源码 utils.py,用 WindowsProactorEventLoopPolicy 替代 loop_factory:
c
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
return asyncio.run(coro)
但修改第三方工具文件会在升级后被覆盖,不推荐。
结论:别在 Windows 原生 PowerShell 里死磕,直接上 WSL2。
五、避坑 2:WSL2 下 ValidationError: task.name Field required
备注:ps中WSL直接进入之前部署的WSL环境(如unbuntu镜像环境)。
- 报错现象:
bash
ValidationError: 1 validation error for TaskConfig
task.name
Field required [type=missing, input_value={'version': '1.0'}, input_type=dict]
-
原因:task.toml 缺少 task 节和 name 字段。
-
解决方案:补全 task.toml:
bash
toml
version = "1.0"
[task]
name = "myapp001/exam_002" # 必填,格式 org/name
六、避坑 3:Docker build context 越界,COPY ./data 找不到
- 报错现象:
bash
COPY ./data/access.log /data/access.log → "/data/access.log": not found
COPY ./solution /myapp001/solution → "/solution": not found
COPY ./data /myapp001/data → "/data": not found
且 transferring context: 2B,说明 build context 几乎是空的。
- 原因:Harbor 默认把 environment/ 目录作为 build context,而 data/ 和 solution/ 在任务根目录(environment/ 的上级),Docker 禁止 COPY 访问 build context 之外的文件。
错误尝试:
在 environment/ 下创建软链接 data -> .../data:Docker 报 too many links。
用 cp -lR 创建硬链接:临时可用,但 Git 不跟踪硬链接,提交后别人克隆会再次失败;且 BuildKit 处理硬链接时可能报 too many links。
- 正确方案:在 environment/ 下创建 docker-compose.yaml,显式指定 build.context 为任务根目录。
删除手动创建的硬链接(安全,不影响原始文件):
bash
cd ~/projects/myapp001/exam_002/environment
rm -rf data solution
创建 environment/docker-compose.yaml:
yaml
services:
main:
build:
context: ..
dockerfile: environment/Dockerfile
Harbor 调用 docker compose 时 --project-directory 是 environment/,所以 context: ... 正好指向任务根目录。
确保 task.toml 中没有残留的 extra_docker_compose 配置。
清理旧 trial 并重新验证:
bash
cd ~/projects/myapp001/exam_002
rm -rf trials/
harbor trials start -p ~/projects/myapp001/exam_002 -a oracle
七、避坑 4:verifier 中 uv 下载失败导致 reward=0
- 报错现象:
bash
curl: (18) HTTP/2 stream 1 was not closed cleanly before end of the underlying stream
failed to download https://github.com/astral-sh/uv/releases/download/0.9.7/uv-x86_64-unknown-linux-gnu.tar.gz
/tests/test.sh: line 11: /root/.local/bin/env: No such file or directory
/tests/test.sh: line 15: uvx: command not found
-
原因:test.sh 依赖 uv 从 GitHub Releases 下载,网络不稳定导致失败,pytest 根本没跑,reward 直接写 0。
-
解决方案:改用 pip 安装 pytest,去掉 uv 依赖。修改 tests/test.sh:
bash
#!/bin/bash
mkdir -p /logs/verifier
pip install --no-cache-dir pytest==8.4.1 pytest-json-ctrf==0.3.5 \
|| { echo "pip install failed"; echo 0 > /logs/verifier/reward.txt; exit 1; }
python -m pytest --ctrf /logs/verifier/ctrf.json /tests/test_outputs.py -rA
if [ $? -eq 0 ]; then
echo 1 > /logs/verifier/reward.txt
else
echo 0 > /logs/verifier/reward.txt
如果 pip 也慢,可加国内镜像:-i https://pypi.tuna.tsinghua.edu.cn/simple。

八、避坑 5:test_outputs.py 断言与 instruction.md 输出格式不匹配
- 报错现象:
bash
AssertionError: missing total requests
assert ('总请求数' in '=== Top IP ===\n192.168.1.100: 4 requests\n\n=== Status Code Distribution ===\n200: 3\n...' or 'total' in ...)
-
原因:test_outputs.py 中检查了 "总请求数" 或 "total",但 instruction.md 定义的输出格式里根本没有这些字段。
-
解决方案:断言必须精确匹配 instruction.md 中定义的格式。例如:
c
from pathlib import Path
import re
REPORT = Path("/output/report.txt")
def test_report_exists():
assert REPORT.exists(), f"report.txt not found at {REPORT}"
def test_report_not_empty():
content = REPORT.read_text().strip()
assert len(content) > 0, "report.txt is empty"
def test_report_contains_required_fields():
content = REPORT.read_text()
assert "=== Top IP ===" in content, "missing '=== Top IP ===' section"
assert "=== Status Code Distribution ===" in content, \
"missing '=== Status Code Distribution ===' section"
assert re.search(r"\d+\.\d+\.\d+\.\d+:\s*\d+\s+requests", content), \
"missing '<IP>: <N> requests' line"
assert re.search(r"\b[1-5]\d{2}:\s*\d+", content), \
"missing '<status_code>: <count>' lines"
九、最终验证与提交前自检
完成上述修复后,重新运行:
bash
cd ~/projects/myapp001/exam_002
rm -rf trials/
harbor trials start -p ~/projects/myapp001/exam_002 -a oracle
应看到:
bash
Rewards: {'reward': 1.0}

提交前必须做一次"干净环境"验证,模拟别人克隆后的行为:
bash
cp -r ~/projects/myapp001/exam_002 /tmp/exam_002_clean
cd /tmp/exam_002_clean
ls -la environment/ # 应只有 docker-compose.yaml 和 Dockerfile,没有 data/solution 链接
harbor trials start -p /tmp/exam_002_clean -a oracle
cat /tmp/exam_002_clean/trials/*/verifier/reward.txt # 应为 1
最终提交的文件结构:
clike
exam_002/
├── task.toml
├── instruction.md
├── environment/
│ ├── docker-compose.yaml ← 关键,指定 context: ..
│ └── Dockerfile
├── solution/
│ ├── solve.sh
│ └── solve.py
├── tests/
│ ├── test.sh
│ └── test_outputs.py
├── data/
│ └── access.log
└── README.md
如:

不要提交 trials/ 目录,也不要依赖任何手动创建的硬链接/软链接。
总结
本地搭建 Harbor 评测环境,核心逻辑不是死磕官方文档,而是顺着 Windows → WSL2 → Docker → Harbor 的依赖关系,提前打通跨系统兼容、部署顺序适配、版本细节兼容这几个卡点。本文覆盖了从异步报错、task.toml 缺字段、build context 越界、硬链接陷阱、verifier 网络失败到断言不匹配的全链路坑点,最终实现 Oracle 自测 reward: 1.0。照着操作,可少走大量弯路。