Rootless Docker挂载宿主机目录权限异常:只读问题排查
问题背景
在Ubuntu 22.04上以非Root模式运行Docker version 24.0.7, build afdd53b,将宿主机目录/home/gpeterso/mjl-dev/web/logs/挂载到容器/usr/local/ROOT/logs/后,容器配置显示挂载为读写模式,但目录属主显示为nobody,容器内mjl用户无法写入。
排查步骤
1. 核对容器与宿主机mjl用户的UID/GID
容器内用户的UID/GID必须与宿主机完全匹配,否则会出现权限映射失效:
# 宿主机查看mjl的UID/GID id mjl # 容器内查看mjl的UID/GID docker exec mjl-dev-web id mjl
若两者UID/GID不一致,需调整容器镜像中mjl用户的ID,或启动容器时通过--user <宿主机mjl的UID>:<宿主机mjl的GID>强制指定映射ID。
2. 检查用户命名空间映射范围
非Root模式Docker依赖subuid/subgid实现用户隔离,需确认启动容器的用户(此处为gpeterso)的映射范围是否覆盖宿主机mjl的UID(3251):
- 当前
gpeterso的subuid范围是100000:65536,宿主机mjl的UID(3251)不在此范围内,导致容器无法将宿主机mjl用户映射到容器内,最终显示为nobody。
解决方法:
- 调整
/etc/subuid和/etc/subgid,为gpeterso添加包含3251的映射范围(需避免与其他用户冲突); - 切换到
mjl用户启动容器,利用其专属的200000:65536映射范围,同时确保容器内mjl用户的UID/GID与宿主机一致。
3. 检查宿主机目录的ACL权限
宿主机目录可能存在ACL限制,导致Docker进程无法正确读写:
# 查看目录ACL配置 getfacl /home/gpeterso/mjl-dev/web/logs/
若缺少gpeterso用户或docker组的读写权限,执行以下命令添加:
setfacl -m u:gpeterso:rwx /home/gpeterso/mjl-dev/web/logs/ setfacl -m g:docker:rwx /home/gpeterso/mjl-dev/web/logs/
4. 验证Docker用户命名空间状态
确认Docker daemon是否正确启用用户命名空间:
docker info | grep "User Namespace"
若显示User Namespace: Enabled则正常;若未启用,编辑/etc/docker/daemon.json添加:
{ "userns-remap": "default" }
重启Docker服务并重新创建容器:
sudo systemctl restart docker
5. 临时验证:禁用用户命名空间
若上述步骤无效,可临时禁用用户命名空间确认问题根源:
编辑/etc/docker/daemon.json设置:
{ "userns-remap": false }
重启Docker后重新创建容器测试。注意:此操作会降低安全性,仅用于排查,不建议长期使用。
内容的提问来源于stack exchange,提问作者GlenPeterson

