WSL Containers (wslc) 操作指南
wslc 是微软随 WSL 3.0.1 发布的 OCI 容器运行时,Windows 上的容器引擎。
命令风格贴近 Docker,但并非完全等价,且有几个容易踩坑的硬约束。
> 适用范围:本文结论基于 wslc 3.0.1 实测。更高版本请先用
> wslc 命令 --help 核对,差异以 --help 为准。
三条必须先知道的约束
动手前先确认这三点,否则命令会以令人困惑的方式失败。
1. 没有全局默认registry,必须给镜像名加前缀
registry-1.docker.io:443 在很多网络环境下不通,而 wslc 3.0.1
既没有 --registry-mirror 参数,也不读 daemon.json。
唯一可行办法是给裸镜像名加加速源前缀:
wslc pull nginx # 会失败/超时
wslc pull docker.m.daocloud.io/library/nginx:latest # 可行
因此优先使用 scripts/wslc.py,它会自动完成前缀拼接:
python scripts/wslc.py pull nginx # 自动解析为带前缀的完整地址
python scripts/wslc.py mirrors # 测速候选加速源,按最快可用者选用
候选源(脚本内置,会自动测速故障转移):
| 源 | 说明 |
|---|---|
docker.m.daocloud.io |
常见可用源 |
docker.1ms.run |
备选 |
网络环境因人而异,mirrors 子命令会实时探测 443 连通性,
请以它的输出为准,不要假定某个源一定可用。
若探测到所有候选都不可达,用 set-mirror <host> 手动指定你自建的代理。
若要让wslc 原生命令也自动加速,可持久化配置:
python scripts/wslc.py set-mirror docker.m.daocloud.io
python scripts/wslc.py set-mirror auto # 恢复自动探测
配置文件位于 ~/.wslc-registry.json。
2. 输出是中文表格,脚本处理要用 --format json
wslc 的输出为 UTF-8 中文表格(如 容器ID映像 命令 ...)。处理数据时改用 JSON:
wslc images --format json # 每行一条 JSON(NDJSON)
wslc ps --format json
支持 --format 的有:list / images / inspect / info。
volume list、network list、system session list 不支持。
3. 会话(session)是有状态的,首次调用有启动开销
wslc system session list 显示当前会话与创建者 PID。每个用户一个会话,
存储在 %LOCALAPPDATA%\wslc\sessions\<session>\storage.vhdx(占用随镜像与容器增长)。
wslc system info # 查看会话、WSL 版本、settings.yaml 路径
wslc system session list
wslc system session terminate# 手动终止会话
wslc settings reset# 恢复内置默认设置(会重置 settings.yaml)
--session <name> 是全局选项,可指定非默认会话。
命令映射(对Docker 的差异)
ps 和 rm 都有官方别名,可以直接用。
| Docker | wslc | 备注 |
|---|---|---|
docker ps |
wslc ps / wslc list / wslc ls |
官方别名,三者等价 |
docker rm |
wslc rm / wslc remove / wslc delete |
官方别名 |
docker rmi |
wslc rmi / wslc image rm |
|
docker cp |
wslc container cp |
必须带 container 层级,且有三处行为差异(见下文兼容层) |
docker exec |
wslc exec / wslc container exec |
|
docker inspect |
wslc inspect / wslc container inspect |
wslc 没有的命令(不要写进脚本):
top diff commit search pause unpause port wait update history
compose buildx swarm stack service secret config context plugin
需要这些时必须用真正的 Docker。scripts/docker_compat.py 会自动定位并转发:
- Windows:
C:\Program Files\Docker\Docker\resources\bin\docker.exe - 其余情况回退到
PATH中的docker
注意 Docker Desktop 即使已安装,com.docker.service 服务也可能处于停止状态,
需先启动服务或直接以管理员运行 Docker Desktop。
run 不支持的参数
--restart 和 --platform 不被支持。重启策略需由WSL Container Desktop
的 restart policy 功能管理。其余常用参数齐备:
-d --rm --name -p -v -e -w --entrypoint --network --memory
--cpus --gpus --health-* --cidfile --mount --tmpfs --ulimit。
命令没有 image 这层
两种写法都可用,但别混写子命令:
wslc pull nginx# 对
wslc image pull nginx # 也对
wslc image pull nginx pull # 错,把 'pull' 当镜像名了
wslc container / wslc image / wslc network / wslc volume /
wslc registry / wslc system 是资源分组前缀,不提供 ps/rm 的组级别名。
Docker 命令兼容层
不想改命令习惯时,用 scripts/docker_compat.py 把 docker 调用翻译成 wslc:
python scripts/docker_compat.py ps
python scripts/docker_compat.py run -d -p 18080:80 nginx
python scripts/docker_compat.py exec <id> cat /etc/hosts
python scripts/docker_compat.py cp 'C:\host\file' <id>:/tmp/ # 自动补 container层级
三个入口:
python scripts/docker_compat.py --capabilities # 打印能力矩阵
python scripts/docker_compat.py --unsupported # 列出 wslc 缺失的能力及替代方案
python scripts/docker_compat.py --use-docker compose up -d # 强制回退真 docker
设计要点:
- 能直译的静默转发,
ps/rm等官方别名直接可用,不打印任何提示。 - 缺失能力明确报错并给替代方案,不用「看起来成功」掩盖问题。
- 仅 docker 能做的命令自动转发给真正的
docker.exe
(compose/buildx/context/plugin/stack/swarm/service/secret)。
输出模式:实时命令透传,其余捕获解码
wslc.run() 按动词分两种处理:
| 动词 | 方式 | 原因 |
|---|---|---|
exec attach logs run start stats |
子进程直接接管终端 | 捕获会把输出全缓冲到结束,logs -f 表现为一条都不输出 |
其余(ps images info ...) |
捕获后按 UTF-8 解码 | 避免中文表格乱码 |
代价是 logs 走透传后不再额外做编码转换。
若终端代码页非 UTF-8 且 logs 出现乱码,改用 wslc logs <id> --help 提到的
容器侧读取方式,或直接在 PowerShell 下调用 wslc。
cp 的三处实测差异(wslc 3.0.1 与 docker 不同)
- 主机侧必须是 Windows 路径。Git Bash 下的
/c/...写法会报「找不到源路径」。 - 目标侧目录必须已存在,否则报
ERROR_PATH_NOT_FOUND。 - 目标目录不存在时会自动创建并嵌套源目录名:
cp <id>:/tmp/cptest/ <host>/back/实际落到<host>/back/cptest/probe.txt。
脚本会在执行前检测并提示这三点。
在 Git Bash 下执行时的路径陷阱
wslc 本身没有路径缺陷,但在 Git Bash(MINGW64) 里,/etc/hostname 这类参数
会被 MSYS 在进程启动前改写成 <Git Bash安装根>/etc/hostname,
容器内命令因此报can't open 'D:/.../etc/hostname'。
scripts/wslc.py 已内置 cygpath 反解还原,所以走脚本即可。
PowerShell / CMD 下直接调用 wslc 完全正常,不受影响。
排查时先确认是哪种 shell,不要误判成引擎缺陷。
已知限制:反解只按「以 Git Bash 安装根开头」判定,因此两个场景无法自动处理:
- 主机侧确实位于 Git Bash 安装目录下的真实文件,会被误还原成 POSIX 路径。
用cygpath -m /可查到该根目录的实际位置;访问该目录下文件时改用 PowerShell。 -v /c/data:/data这类挂载,MSYS 会改写成C:\data;<Git Bash根>\data
的分号形态,超出前缀匹配能力。请直接写-v 'C:\data:/data'。
常用工作流
# 拉取(裸名经脚本自动加前缀)
python scripts/wslc.py pull nginx
python scripts/wslc.py pull redis:7
# 运行:-d 后台,-p 映射端口
python scripts/wslc.py run -d -p 18080:80 nginx
curl http://localhost:18080 # 验证
# 一条命令跑完并看输出(无 -d)
python scripts/wslc.py run --rm alpine:3.20 echo hello
# 查看
python scripts/wslc.py ps -a # -a 含已停止
python scripts/wslc.py images --format json
python scripts/wslc.py logs <id>
python scripts/wslc.py stats
# 进入容器
python scripts/wslc.py exec -it <id> sh
# 清理
python scripts/wslc.py rm -f <id>
python scripts/wslc.py raw prune # 清理已停止容器/未用镜像
scripts/wslc.py 额外提供两个调试子命令:
python scripts/wslc.py resolve nginx redis:7 # 只显示解析结果,不执行
python scripts/wslc.py raw <原生命令> # 跳过前缀改写,原样转发
Registry 凭据
凭据不落盘在wslc 自己的配置里,由 wslc login 写入凭据存储
(%LOCALAPPDATA%\wslc\settings.yaml 里可配 credentialStore: wincred 或 file):
wslc login docker.m.daocloud.io -u <user># 密码交互输入
wslc registry logout docker.m.daocloud.io
配套 GUI:WSL Container Desktop
CLI 之外还有图形界面 WSL Container Desktop(社区项目,非微软官方)。
两者可配合:Desktop 负责可视化与编排,CLI 负责脚本化。
配置位于
%LOCALAPPDATA%\Packages\<PackageFamilyName>\LocalCache\Local\WslContainerDesktop\settings.json:
注意这是 MSIX 重定向后的路径,不是 %LOCALAPPDATA%\WslContainerDesktop\。
<PackageFamilyName> 需自行查填,用 scripts/wcd-registry.ps1 可自动解析。
属性名必须 PascalCase(反序列化无JsonSerializerOptions,大小写敏感)。
Desktop 的 Registries 无法把加速源设为默认(v2.2.0 实测):SettingsService.Load()
硬编码 new List { RegistryEntry.DockerHub() } 把 Docker Hub 放第一位,
且所有对话框都是 SelectedIndex = 0。GUI 下拉框每次需手动选。
该行为属应用实现细节,新版本可能已修,遇到时以实际界面为准。
Desktop 的 Compose 是应用内自实现的 desktop-as-daemon,关掉应用编排即停,
不能用于无人值守恢复。
排查思路
| 现象 | 检查方向 |
|---|---|
| 拉取超时 | 源不通。python scripts/wslc.py mirrors 测连通性 |
| 中文输出乱码 | 终端代码页问题,脚本已按 UTF-8 解码;或用 --format json |
| 首次命令很慢 | 会话首次启动开销,后续复用 |
命令不存在 |
确认该命令在 wslc 中确实存在(见上文缺失清单) |
| 磁盘占用增长 | %LOCALAPPDATA%\wslc\sessions\<session>\storage.vhdx,用 prune 回收 |
can't open 'D:/.../etc/xxx' |
不是 wslc 缺陷,是 Git Bash 的 MSYS 路径改写。改用 PowerShell 调用,或走 scripts/wslc.py(已内置反解) |
找不到源路径 |
cp 主机侧用了 Git Bash 的 /c/... 写法,须改为 C:\... |
extraction point is not a directory |
cp 目标侧目录不存在,先建目录 |
详细命令清单与参数见 references/commands.md。