# 修复 WSL2 Arch Linux 里 Podman Build 的 Newuidmap 报错


在 Windows 上的 WSL2 Arch Linux 里跑 rootless Podman，构建镜像时可能直接卡在 user namespace 初始化阶段：

```bash
podman build . -t game-crawler:latest
```

报错类似这样：

```text
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](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md) 里写到，rootless Podman 需要 `/etc/subuid` 和 `/etc/subgid` 里的 subordinate UID/GID 范围。`newuidmap(1)` 的手册也说明，它负责设置 user namespace 的 UID 映射，并会检查调用者是否被 `/etc/subuid` 授权。

也就是说，rootless Podman 创建容器命名空间时，需要这两个辅助程序：

```text
/usr/bin/newuidmap
/usr/bin/newgidmap
```

在 Arch Linux 里它们来自 `shadow` 包。如果二进制没有 setuid，也没有对应 file capability，普通用户就没有权限完成 UID/GID 映射，Podman build 会在创建 namespace 时失败。

## 检查当前状态

先看文件权限和 capability：

```bash
stat -c '%A %U:%G %a %n' /usr/bin/newuidmap /usr/bin/newgidmap
getcap /usr/bin/newuidmap /usr/bin/newgidmap
```

出问题时可能是这样：

```text
-rwxr-xr-x root:root 755 /usr/bin/newuidmap
-rwxr-xr-x root:root 755 /usr/bin/newgidmap
```

`getcap` 没有任何输出。

再确认当前用户有 subordinate ID：

```bash
grep "^$USER:" /etc/subuid /etc/subgid
```

正常应该有类似输出：

```text
/etc/subuid:nite:100000:65536
/etc/subgid:nite:100000:65536
```

如果这里没有当前用户的记录，需要先补 `/etc/subuid` 和 `/etc/subgid`。如果这里已经有记录，但 `newuidmap/newgidmap` 没有 setuid 或 capability，那就继续修权限。

## 用 file capability 修复

优先给两个辅助程序加最小 capability：

```bash
sudo setcap cap_setuid=ep /usr/bin/newuidmap
sudo setcap cap_setgid=ep /usr/bin/newgidmap
```

检查结果：

```bash
getcap /usr/bin/newuidmap /usr/bin/newgidmap
```

应该看到：

```text
/usr/bin/newuidmap cap_setuid=ep
/usr/bin/newgidmap cap_setgid=ep
```

Arch 里 `/usr/sbin` 通常是指向 `bin` 的链接，所以报错路径即使写的是 `/usr/sbin/newuidmap`，修 `/usr/bin/newuidmap` 也是同一个文件。

## 验证 rootless namespace

不用完整 build。先用 `podman unshare` 验证 UID/GID 映射能不能建起来：

```bash
podman unshare sh -c 'echo uid_map:; cat /proc/self/uid_map; echo gid_map:; cat /proc/self/gid_map'
```

修好后会看到类似：

```text
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：

```bash
podman build . -t game-crawler:latest
```

## 如果 setcap 不可用

先确认 `setcap/getcap` 是否存在：

```bash
command -v setcap getcap
```

如果没有，安装提供它们的包：

```bash
sudo pacman -S libcap
```

还有一种传统做法是给 `newuidmap/newgidmap` 加 setuid：

```bash
sudo chmod u+s /usr/bin/newuidmap /usr/bin/newgidmap
```

检查：

```bash
stat -c '%A %U:%G %n' /usr/bin/newuidmap /usr/bin/newgidmap
```

期望看到 `-rwsr-xr-x`。如果 file capability 可用，优先用 `setcap`，权限范围更窄。


---

> 作者: Nite  
> URL: https://www.nite07.com/zh-cn/posts/wsl-rootless-podman-newuidmap/  

