bigywater.tech
Docker · 28

挂载卷的权限:容器内 uid 与宿主机 uid 的对应

容器里的 uid 和宿主机的 uid 是什么关系?为什么有时候卷里的目录非 root 用户写不进去?这篇分别在 bind mount 和命名卷上实测文件属主的映射规则。

uid 501
容器 root 在 bind mount 里创建的文件,在 macOS 宿主机上的属主
Permission denied
root 属主的空命名卷目录,--user 1000 写入的结果
1000 1000
命名卷在虚拟机里的真实属主

bind mount(macOS)

实测 · 本机执行输出
  容器里 root(uid 0)创建的 by-root.txt,在宿主机上:uid=501 gid=20 mode=0o644
  宿主机创建的 by-host.txt(宿主机上 uid=501 gid=20 mode=0o640),容器里 ls -ln:-rw-r----- 1 0 0

容器里 root 创建的文件,在宿主机上归宿主机用户(uid 501);宿主机用户的文件在容器里显示成 root 的(0 0)。这是 Docker Desktop 在 macOS 上的行为,不能推广到 Linux 宿主机——Linux 上 bind mount 的 uid 是原样的,我没有测。

写入权限与 chown

实测 · 本机执行输出
  宿主机目录 mode 755、属主是宿主机用户:--user 1000 写入 → 退出码 0;写成功
  文件在宿主机上:uid=501 gid=20 mode=0o644
  容器里 chown 1234:1234 并 chmod 600 之后,容器里看:-rw------- 1234 1234;宿主机上:uid=501 gid=20 mode=0o600

uid 1000 的容器用户可以往宿主机上 755、属主是宿主机用户的目录里写文件;容器里 chown 1234:1234 之后容器里看到 1234,宿主机上仍是 501;chmod 600 则在宿主机上也生效。也就是说,在这种 bind mount 上不要指望靠 uid 做访问控制。

命名卷与镜像目录的属主

实测 · 本机执行输出
  镜像里 /rootonly 属主是 root(0:0):空命名卷挂上去,--user 1000 → 退出码 1;drwxr-xr-x 0 0 | sh: can't create /rootonly/f.txt: Permission denied
  镜像里 /owned 属主是 1000:1000(并含 seed.txt):空命名卷挂上去,--user 1000 → 退出码 0;drwxr-xr-x 1000 1000 | 1000:1000 /owned/seed.txt | 写成功
  事后用 root chown 1000:1000 这个卷的根目录(drwxr-xr-x 1000 1000),再用 --user 1000 写入 → 写成功

空命名卷第一次挂载时,镜像里该目录的内容连同属主一起复制进卷(根目录本身也一样)。镜像里目录是 root 的,非 root 的容器用户就写不进去;在 Dockerfile 里先 chown 目录是一种做法,事后用 root 容器 chown 卷的根目录是另一种。

卷里的真实 uid

实测 · 本机执行输出
  Docker Desktop 虚拟机里 /var/lib/docker/volumes/bwlab-c23-owned/_data:-rw-r--r-- 1 1000 1000 f.txt ; -rw-r--r-- 1 1000 1000 seed.txt

进入虚拟机看卷的目录,文件属主就是 1000 1000,没有映射。所以同一个命名卷换一个 uid 不同的镜像去用,就可能遇到权限问题(本文没有演示这个场景)。

分步演示

挂载卷的权限
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。宿主机用户 uid 501(macOS);bind mount 的宿主机目录在本项目临时目录下;命名卷属主在虚拟机里用特权容器加 nsenter 读取(方法见 c19);实验后已删除容器、卷、镜像和临时目录
    • 没有验证:Linux 宿主机的 bind mount、--userns-remap(见后面的 userns 一篇)、SELinux 标签(:z / :Z)、docker run --user 与 fsGroup 之类的 Kubernetes 方案、NFS 卷、Windows 宿主机
    京ICP备2026067502号-1京公网安备11010502063487号