修复 WSL2 Arch Linux 里 Podman Build 的 Newuidmap 报错
在 Windows 上的 WSL2 Arch Linux 里跑 rootless Podman,构建镜像时可能直接卡在 user namespace 初始化阶段:
podman build . -t game-crawler:latest报错类似这样:
WARN[0000] "/" is not a shared mount, this could cause issues or missing mounts with rootless containers
ERRO[0000] running `/usr/sbin/newuidmap 61029 0 1000 1 1 100000 65536`: newuidmap: Could not set caps
Error: cannot set up namespace using "/usr/sbin/newuidmap": should have setuid or have filecaps setuid: exit status 1"/" is not a shared mount 只是 warning。这里真正让 build 失败的是 newuidmap: Could not set caps。
触发条件
这是 rootless Podman 的问题,不是 Dockerfile 本身的问题。
Podman 官方的 rootless tutorial 里写到,rootless Podman 需要 /etc/subuid 和 /etc/subgid 里的 subordinate UID/GID 范围。newuidmap(1) 的手册也说明,它负责设置 user namespace 的 UID 映射,并会检查调用者是否被 /etc/subuid 授权。
也就是说,rootless Podman 创建容器命名空间时,需要这两个辅助程序:
/usr/bin/newuidmap
/usr/bin/newgidmap在 Arch Linux 里它们来自 shadow 包。如果二进制没有 setuid,也没有对应 file capability,普通用户就没有权限完成 UID/GID 映射,Podman build 会在创建 namespace 时失败。
检查当前状态
先看文件权限和 capability:
stat -c '%A %U:%G %a %n' /usr/bin/newuidmap /usr/bin/newgidmap
getcap /usr/bin/newuidmap /usr/bin/newgidmap出问题时可能是这样:
-rwxr-xr-x root:root 755 /usr/bin/newuidmap
-rwxr-xr-x root:root 755 /usr/bin/newgidmapgetcap 没有任何输出。
再确认当前用户有 subordinate ID:
grep "^$USER:" /etc/subuid /etc/subgid正常应该有类似输出:
/etc/subuid:nite:100000:65536
/etc/subgid:nite:100000:65536如果这里没有当前用户的记录,需要先补 /etc/subuid 和 /etc/subgid。如果这里已经有记录,但 newuidmap/newgidmap 没有 setuid 或 capability,那就继续修权限。
用 file capability 修复
优先给两个辅助程序加最小 capability:
sudo setcap cap_setuid=ep /usr/bin/newuidmap
sudo setcap cap_setgid=ep /usr/bin/newgidmap检查结果:
getcap /usr/bin/newuidmap /usr/bin/newgidmap应该看到:
/usr/bin/newuidmap cap_setuid=ep
/usr/bin/newgidmap cap_setgid=epArch 里 /usr/sbin 通常是指向 bin 的链接,所以报错路径即使写的是 /usr/sbin/newuidmap,修 /usr/bin/newuidmap 也是同一个文件。
验证 rootless namespace
不用完整 build。先用 podman unshare 验证 UID/GID 映射能不能建起来:
podman unshare sh -c 'echo uid_map:; cat /proc/self/uid_map; echo gid_map:; cat /proc/self/gid_map'修好后会看到类似:
uid_map:
0 1000 1
1 100000 65536
gid_map:
0 1000 1
1 100000 65536这里的 1000 是当前 WSL 用户的 UID,100000 65536 来自 /etc/subuid 和 /etc/subgid。
然后重新 build:
podman build . -t game-crawler:latest如果 setcap 不可用
先确认 setcap/getcap 是否存在:
command -v setcap getcap如果没有,安装提供它们的包:
sudo pacman -S libcap还有一种传统做法是给 newuidmap/newgidmap 加 setuid:
sudo chmod u+s /usr/bin/newuidmap /usr/bin/newgidmap检查:
stat -c '%A %U:%G %n' /usr/bin/newuidmap /usr/bin/newgidmap期望看到 -rwsr-xr-x。如果 file capability 可用,优先用 setcap,权限范围更窄。