You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Docker容器内执行mkdir遇到Permission Denied的问题排查

Docker容器内执行mkdir遇到Permission Denied的问题排查

看起来你遇到的问题核心是权限匹配不对应,咱们一步步拆解来看:

先看你贴的ls -l输出:

drwxr-xr-x    2 755      djuser        4096 Dec  5 11:07 media

这里的755是目录的数字UID所有者,而你当前运行的djuser属于djuser组。755权限的目录,组用户只有r-x(读+执行)权限,没有写权限——这就是你没法在media里创建uploads目录的直接原因!

那为什么明明Dockerfile里执行了chown -R djuser:djuser /vol,结果media的所有者变成了数字UID 755?大概率是卷挂载的权限覆盖导致的:

最可能的原因:Bind Mount卷的宿主机权限冲突

如果你在docker-compose.yml里把/vol/web挂载成了宿主机的Bind Mount目录(比如./vol:/vol/web),那容器里/vol/web的权限会直接继承宿主机对应目录的权限。

  • 假设宿主机上./vol/web/media的所有者是UID 755的用户,那容器里看到的所有者就是755,而你的djuser的UID和755不匹配,只能以组用户的身份访问,自然没有写权限。

解决方案(按推荐度排序)

1. 改用Docker Named Volume

如果不需要宿主机目录直接映射,换成Named Volume的话,Docker会自动继承镜像里的目录权限:
docker-compose.yml里配置:

volumes:
  web_media:
  web_static:

services:
  app:
    # ... 其他配置
    volumes:
      - web_media:/vol/web/media
      - web_static:/vol/web/static

这样启动后,Named Volume会继承你Dockerfile里设置的djuser:djuser权限,djuser作为所有者拥有rwx权限,就能正常创建目录了。

2. 固定djuser的UID与宿主机匹配

如果必须用Bind Mount,那让容器里djuser的UID和宿主机对应目录的所有者UID保持一致:

  • 先在宿主机执行id -u,拿到你当前用户的数字UID(比如1000)
  • 修改Dockerfile里的adduser命令,指定固定UID:
RUN \
adduser -u 1000 --disabled-password --no-create-home djuser && \
mkdir -p /vol/web/media && \
mkdir -p /vol/web/static && \
chown -R djuser:djuser /vol && \
chmod -R 755 /vol

重新构建镜像后,容器里的djuserUID就是1000,和宿主机目录所有者一致,此时djuser就是media目录的所有者,拥有写权限。

3. 用Entrypoint脚本自动处理权限(无需手动sudo)

如果需要容器启动时自动创建目录,又不想每次切root,可以写一个简单的entrypoint脚本:

  1. 在项目根目录创建entrypoint.sh
#!/bin/sh
# 以root身份创建uploads目录(如果不存在)
mkdir -p /vol/web/media/uploads
# 把目录权限交还给djuser
chown -R djuser:djuser /vol/web/media/uploads
# 切换回djuser执行原启动命令
exec su-exec djuser "$@"
  1. 修改Dockerfile,安装su-exec(alpine轻量的权限切换工具)并设置entrypoint:
# 原有RUN命令之后加:
RUN apk add --no-cache su-exec
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

这样每次容器启动时,会自动帮你创建目录并设置正确权限,全程不需要手动干预root操作。

最后验证

不管用哪种方案,都可以先在容器里跑个命令确认权限:

docker-compose run --rm app sh -c "whoami && id && ls -ld /vol/web/media"

如果输出里media的所有者是djuser(或者和djuser的UID一致),那权限就没问题了,再试mkdir应该就能成功。

备注:内容来源于stack exchange,提问作者RomanMin

火山引擎 最新活动