核心是UID/GID数字必须一致,Linux只认ID不认用户名;先用ls -ldn和stat查宿主机目录UID/GID,再用docker run id查容器实际运行UID/GID,比对不一致即为根源,可通过--user显式指定或chown统一。

直接看 UID 是否对得上,这是最核心的排查动作。Linux 文件权限只认数字 ID,不认用户名;容器里叫 appuser、宿主机上叫 dev,只要 UID 不一样,照样报 Permission denied。
第一步:查宿主机目录的实际 UID/GID
别只看 ls -l 显示的用户名,要加 -n 参数显示数字 ID:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- ls -ldn /path/to/mounted/dir —— 查目录本身的 UID/GID 和权限位(例如 drwxr-xr-x 2 1001 1001)
- stat -c "%u %g %a" /path/to/mounted/dir —— 直出 UID、GID、八进制权限(如 1001 1001 755)
- 如果挂载的是 NFS 或其他网络文件系统,还要确认服务端是否配置了 anonuid/anongid,避免映射成 nobody
第二步:查容器内进程实际运行的 UID/GID
不能只信 Dockerfile 里的 USER 行,得看运行时真实身份:
- 启动一个临时容器查:docker run -v /host/path:/test alpine id
- 或进已运行容器:docker exec -it container_name sh -c 'id; ps aux | grep -E "(USER|PID)"'
- 特别注意镜像是否预设了非 root 用户(如 mysql 默认 uid=999,nginx 常用 uid=101),这些值在不同发行版或版本中可能有差异
第三步:比对并快速验证修复路径
两边 UID/GID 数字不一致,就是根源。验证方式简单直接:
- 若宿主机是 1001:1001,容器当前是 0:0(root),就试:docker run -v /host/path:/container/path --user 1001:1001 image:tag ls -l /container/path
- 若成功列出内容,说明问题闭环;失败则继续检查 SELinux 或 AppArmor 干扰(CentOS/RHEL 上先 sudo setenforce 0 临时关闭验证)
- 生产环境建议用固定数字(如
--user 1001:1001),避免$(id -u)这类命令替换在 CI/CD 中引入不确定性

















