快速修复
# 一键:把宿主目录属主改成容器内 uid(示例容器 uid 1000)
sudo chown -R 1000:1000 ./data && docker run --rm -u 1000:1000 -v "$PWD/data:/data" <镜像> ls /data
你会遇到什么
容器能正常启动、挂载也能看到(ls 有文件),但进程一读一写就报 Permission denied。你以为是挂载没成功——其实挂载成功了,是容器内进程的 uid 和宿主目录的属主对不上。常见于按安全建议切非 root 用户跑容器(-u 1000:1000、compose user:、镜像内置 USER)之后;镜像默认 root 跑时一切正常,一切换立刻暴露。
本文路径:快速修复(30 秒一段命令)→ 一步步排查(可跳读)→ 原理与变体(症状/原因/证据)。赶时间直接跳到「快速修复」。
为什么会这样
Linux 权限按 uid/gid 匹配,bind mount 不做所有权转换:容器进程的 uid 直接按宿主目录文件的属主/权限来判定。典型错位:宿主文件属主 root(uid 0),容器进程以非 0 uid 运行 → 读 600 被拒、写不进。
常见误区:换 named volume 也不自动解决——docker 首次创建 named volume 时把目录初始化为 root:root 755,非 root 容器照样 Permission denied(实测复现)。
实测环境:WSL Ubuntu,docker 29.1.3,alpine:3.20,2026-08-29。
Linux 权限判定是「进程 uid/gid × 文件属主/权限位」的匹配,bind mount 只是把宿主目录挂进容器,不做 uid 映射也不做所有权转换——容器里 uid 1000 的进程读写宿主上 uid 0 的 600 文件,判定结果与宿主机上一个普通用户读写 root 文件完全一致。
named volume 首次创建时 docker 初始化为 root:root 755,所以非 root 容器换 named volume 照样 Permission denied。
确定性推论:别猜「容器里应该能写」,先 docker run --rm -v <目录>:/data <镜像> ls -ln /data 看实际属主;解法三选一——宿主侧 chown -R 1000:1000 对齐 uid、容器以 root 跑(临时/开发)、user namespace 重映射(生产);chown 改的是宿主文件,容器内外两个方向同时生效。
一步步来
1. 确认是权限不是挂载 — 必做
docker run --rm -u 0:0 -v "$PWD/data:/data" <镜像> ls -l /data
root 容器能读、非 root 容器不能 → 权限问题(实测对照)。
2. 调整宿主目录属主 — 必做
sudo chown -R 1000:1000 ./data
chown 成容器内 uid——一次性修正,适合数据目录属主固定不变的场景(实测:chown 后非 root 容器读取成功,exit 0)。
3. 镜像内置用户时查官方文档 — 必做
很多官方镜像写明「请用 -u 1000:1000 运行」(如 blocky 内部用户是 uid 100),按文档对齐,不要猜。
4. named volume 的权限初始化 — 必做
若镜像内目标目录属主不匹配,需要在 entrypoint / init 容器里 chown;镜像目录属主本来正确(如镜像里建好 /data 且属主 1000)时才能直接享受 volume 自动初始化。
5. 临时应急 — 必做
-u 0:0 以 root 跑容器可绕过,但破坏最小权限原则,仅限本机调试。
怎么确认修好了
docker run --rm -u 1000:1000 -v "$PWD/data:/data" <镜像> touch /data/write-test && echo OK
能写入即成功。
实测:-u 1000:1000 读 root 属主 600 文件 → Permission denied(exit 1);root 容器读同一挂载 → 成功;宿主 chown 1000:1000 后非 root 容器 → 成功;named volume 初始化属主 root:root 755,非 root 容器 touch → 仍 Permission denied(误区坐实)。
其它环境的表现
| 环境 | 说明 |
|---|---|
| bind mount(-v 宿主机:容器) | 最典型,chown 宿主目录对齐 uid |
| named volume | 不自动解决;镜像目录属主正确才行 |
| Docker Desktop(Windows/macOS) | 同样高频,挂载目录属主与容器 uid 对不上 |
| 镜像内置 USER | 查官方文档的推荐 -u,按文档对齐 |
症状
容器能正常启动、挂载也能看到(ls 有文件),但进程一读一写就报权限错误:
cat: can't open '/data/rootfile': Permission denied
touch: /data/write-test: Permission denied
mkdir: cannot create directory '/data/xxx': Permission denied
cannot create temp cache file in /cache: open /cache/xxx.tmp: permission denied
特征:
- 容器起得来、目录可见,只是读写被拒——容易误判成「挂载没成功」;
- 常见于非 root 容器:镜像内置
USER、docker run -u UID:GID、compose 的user: "1000:1000"; - bind mount(
-v /宿主机路径:/容器路径)最典型;named volume 也会出现; - Windows/macOS 的 Docker Desktop 同样高频(挂载自宿主目录,属主与容器内 uid 对不上)。
原因
Linux 权限按 uid/gid 匹配,bind mount 不做所有权转换:容器进程的 uid 直接按宿主目录文件的属主/权限来判定。典型错位是宿主文件属主 root(uid 0)或别的 uid(如 1000),而容器进程以非 0 uid 运行 → 读 600 / 写不进去。镜像默认以 root 跑时一切正常,一旦按安全建议切非 root 用户跑,问题立刻暴露。
常见误区:换 named volume 也不自动解决——docker 首次创建 named volume 时把目录初始化为 root:root 755,非 root 容器照样 Permission denied(实测复现)。
解法
- 调整宿主目录属主:
sudo chown -R 1000:1000 ./data(chown 成容器内 uid)——一次性修正,适合数据目录属主固定不变的场景。 - 镜像内置用户时查官方文档:很多官方镜像写明「请用
-u 1000:1000运行」(如 blocky 内部用户是 uid 100),按文档对齐,不要猜。 - named volume 的权限初始化:若镜像内目标目录属主不匹配,需要在 entrypoint / init 容器里 chown;镜像目录属主本来正确(如镜像里建好
/data且属主 1000)时才能直接享受 volume 自动初始化。 - 临时应急:
-u 0:0以 root 跑容器可绕过,但破坏最小权限原则,仅限本机调试。
验证证据
- 本地实测(2026-08-29,WSL Ubuntu,docker 29.1.3,alpine:3.20):
- 准备:宿主目录放 root 所有(uid 0)、600 权限的文件;
- 复现:
docker run --rm -u 1000:1000 -v /tmp/vol-test:/data alpine cat /data/rootfile→Permission denied(exit 1); - 对照:不加
-u的 root 容器读同一挂载 → 成功(排除挂载本身问题); - 修复 A:宿主
chown 1000:1000后非 root 容器读取 → 成功(exit 0); - 修复 B:
-u 0:0对齐宿主 → 成功(exit 0); - 误区验证:
docker volume create后-u 1000:1000容器 touch named volume →Permission denied(exit 1);ls -ld /data证实 volume 初始化属主root:root 755→ named volume 不自动解决权限;root 容器写同一 named volume → 成功。 - 实测复现日志(2026-08-29)
相关 canonical
按「前置 → 同根 / 同域 / 相关」读:
- 前置(先排除):
- Docker daemon 连不上(前置:能启动容器 = daemon 正常,权限错在挂载层)
适用工具 (1)
本问题方案已挂到下列工具的方案页——从工具页也能回到这里,双向可达。
docker · 外部工具成套方案 (组合包)
这个问题包含在下列成套安装方案中。
- docker-compose 开发环境 verified
来源与证据
← 编码代理与终端 问题域 | 问题货架 | 遇到其它问题?去 问题空间 提交求助卡