朕喜技术(ZhenxiJS)
2026.09.05
1 分钟阅读

Docker named volume 非 root 用户 Permission denied 解决

关键词:Docker permission denied、docker non-root user、named volume owner root、docker compose chown、Errno 13 Permission denied docker、容器内非root写入挂载卷失败

问题背景

Docker 容器以非 root 用户(如 appuser uid=1000)运行,数据目录 /data/uploads 挂载了 named volume。应用写入文件时报:

PermissionError: [Errno 13] Permission denied

ls -la 显示挂载目录 owner 是 root(0:0),而运行用户 uid=1000 无写权限。

复现步骤

# scenario/2026-09-05-0001/
docker compose up -d --build
docker compose exec app python3 /app/app.py

复现 Dockerfile 片段(问题版本):

RUN useradd -m -u 1000 appuser
RUN mkdir -p /data/uploads     # root 创建,未 chown
USER appuser

根本原因

Docker named volume 首次挂载时,会从镜像中挂载点目录继承所有权(owner/group/权限)。因 Dockerfile 用 root 创建了 /data/uploads 且未 chown,volume 的 owner 也变成 root。容器内以 appuser(uid=1000) 运行,对 root 拥有的目录无写权限。

一句话:named volume 默认以 root 持有所有权,需在镜像构建时把挂载点 chown 给运行用户。

解决办法

修改 Dockerfile,在 USER appuser 之前 chown 挂载目录:

RUN mkdir -p /data/uploads && chown -R appuser:appuser /data/uploads

然后必须删除旧 volume 再重建(否则旧 volume 仍是 root owner,改动不生效):

docker compose down -v     # 注意会清除 volume 数据
docker compose up -d --build

验证

docker compose exec app python3 /app/app.py
# → 目录所有者为 appuser(uid=1000):appuser(gid=1000)
# → 成功写入 /data/uploads/hello.txt ✓

经验与避坑

  1. 改 Dockerfile 只对全新 volume 有效:named volume 首次创建时才从镜像挂载点继承所有权。volume 已存在则需 docker compose down -v 删除重建。生产删卷前务必备份。
  2. 更健壮的生产方案:用 entrypoint 动态 chown——容器以 root 启动 → entrypoint 里执行 chown -R appuser:appuser /data/uploads → 用 gosu/su 降权切换到 appuser 运行应用。这样即使 volume 已存在也能动态修复,且不删数据。
  3. K8s 场景:用 securityContext.fsGroup 让集群自动 chown 持久卷,或加一个 initContainer 负责 chown。
  4. 检查权限问题的命令:docker compose exec app id 看运行 uid;docker compose exec app ls -la /data 看挂载目录 owner。

技术栈与环境

  • Linux + Docker Compose v2
  • 镜像:python:3.11-slim
  • Python 应用(os.access/open 判断写权限)
  • 非 root 用户 appuser(uid=1000)

可复现命令

cd scenario/2026-09-05-0001
docker compose up -d --build
docker compose exec app python3 /app/app.py   # 复现:PermissionError
# 修复后重新验证:
docker compose down -v && docker compose up -d --build
docker compose exec app python3 /app/app.py   # 成功写入 ✓

版权声明

本文为博主原创文章,遵循 CC BY-NC-SA 4.0 许可协议。 转载请注明出处:http://localhost/blogs/2026-09-05-0008-docker-permission

分享这篇文章