在 rootless 容器中,用非 root 用户无法操作 volume 里的文件
问题描述
在 rootless 容器中,用非 root 用户对 volume 里的文件进行写操作,会提示 Permission denied
。
详见 https://github.com/containerd/nerdctl/issues/2334
必要条件
- rootless 模式。
- 镜像的默认用户不是 root。
- 用
-v
参数从主机挂载目录到容器。
我试了 docker v24.0.2,nerdctl v1.7.2,podman v4.0.1,结果都一样。
复现方法
- Install rootless nerdctl.
- Create a Dockerfile
FROM alpine:3
RUN adduser -D admin
USER admin
WORKDIR /home/admin
- Create a Makefile
cat Makefile
.PHONY: build
build:
@nerdctl build -t image-name .
.PHONY: run
run:
@nerdctl run -it --rm -v $(PWD)/abc:/home/admin/abc image-name sh
mkdir abc
make build
to build imagemake run
to create a container and enter the shell.touch ./abc/d
touch: ./abc/d: Permission denied
失败方法
docker run --user 1000:1000
❌ 无效docker run --userns=keep-id
❌ 目前 nerdctl 没--userns
选项,docker 支持,但没有 keep-id 这个选项。podman 支持,但无效。docker run --user 1000:1000 --userns=keep-id
❌ 无效docker run -v /xxx:/xxx:Z
❌ 无效docker run --user 1000:1000 --userns=keep-id -v /xxx:/xxx:Z
❌ 无效
--user
的值是容器里的用户 uid:gid
,可以在容器里执行 id
,确认是不是 uid=1000, gid=1000
。
解决方法
单独创建一个 volume。直接把文件写在 volume 里,不直接从宿主机挂载文件。
在目标容器启动之前,先用其他镜像挂载 volume,把文件放进去,用 chown
修改文件权限。然后把这个 volume 挂到目标容器里。 具体执行代码参考下面。
# docker 可以换成 nerdctl, podman
docker volume create vol
docker run --rm -v vol:/data alpine sh -c 'mkdir /data/abc && chown 1000:1000 /data/abc'
或者,可以复制宿主机的文件到容器的 volume 里。
docker run --name temp --rm -d -v vol:/data alpine sleep 30
docker cp ./config.yaml temp:/data/
可以进到容器看看 volume 里的文件,docker run --rm -it -v vol:/data alpine:3
。