元数据
| id | docker-volume-permission | 收录 | 2026-08-29 |
|---|---|---|---|
| 问题域 | 编码代理与终端 | 主题分组 | 权限与安全 |
| 适用工具 | docker · 外部工具 | ||
症状
容器能正常启动、挂载也能看到(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(实测复现)。
解法
1. **调整宿主目录属主**:`sudo chown -R 1000:1000 ./data`(chown 成容器内 uid)——一次性修正,适合数据目录属主固定不变的场景。
2. **镜像内置用户时查官方文档**:很多官方镜像写明「请用 `-u 1000:1000` 运行」(如 blocky 内部用户是 uid 100),按文档对齐,不要猜。
3. **named volume 的权限初始化**:若镜像内目标目录属主不匹配,需要在 entrypoint / init 容器里 chown;镜像目录属主本来正确(如镜像里建好 `/data` 且属主 1000)时才能直接享受 volume 自动初始化。
4. **临时应急**:`-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)
来源与证据
素材来源:https://github.com/0xERR0R/blocky/issues/2165
验证证据:Evidence details kept locally (2026-08-29)