Docker 挂载目录报 Permission denied:确认 SELinux 标签与共享范围
Docker bind mount 报 Permission denied 时,先核对普通权限与 SELinux 审计,再决定私有 Z 或共享 z 标签、容器重建及宿主标签恢复范围。
Linux 宿主机启用了 SELinux,Docker 容器把项目目录挂载到 /code,却在创建或读取文件时报告 Permission denied。目录在宿主机上可以访问,普通权限看着也够,这时应检查 SELinux 是否拒绝了容器进程访问该文件。
这条处理路径针对启用 SELinux 的 Linux Docker 宿主机及 bind mount。SELinux 已关闭、目录没有真正挂进容器、挂载为只读,或者进程的 UID/GID 不匹配,都要按各自原因处理。不能只凭同一条错误就给所有挂载加 :Z。
先把普通权限和安全标签分开
核对 Compose 实际解析的宿主机路径、容器内路径,以及容器现有挂载记录。相对路径应按项目配置的解析规则确认,远程 Docker 服务使用的是服务端宿主机目录。容器里出现空目录,也不等于发生了 SELinux 拒绝。
同时确认应用实际运行用户、目录及父目录的访问权限、目标文件是否可写,以及挂载是否为只读。即使后来修正了标签,这些条件仍须满足。不要先把整棵项目目录改成 777,或让应用以 root 运行来试错。
下面是宿主机上的只读检查示例,路径需换成实际挂载目录:
getenforce
ls -Zd -- /srv/example-app
sudo ausearch -m AVC,USER_AVC -ts recent
Enforcing 表示正在执行策略;Permissive 会记录本应拒绝的访问,但不靠 SELinux 阻断操作;Disabled 时不能把当前失败归给 SELinux。ls -Z 显示安全上下文,-d 查看目录本身。
审计查询中的 recent 指最近约十分钟。把 AVC 的时间、进程、访问动作和目标路径与失败请求对应起来:确实是容器访问这个挂载目录被拒绝,才进入标签处理。审计输出可能包含业务路径,应按内部诊断资料保管。没有查询结果也不能独自排除策略问题,还要核对审计服务、记录时间和日志收集情况。
私有目录用 Z,共享目录用 z
普通本机 Compose 的短格式可以指定标签处理。以下只是挂载配置片段,应保留服务其余设置:
services:
web:
volumes:
- ./app:/code:Z
Z 将该目录按当前容器的私有访问范围重新标记。适合由这个容器独占的应用目录,前提是宿主机上的其他服务不需要按原标签访问它。
若业务设计中多个容器必须共同访问同一份目录,应评估使用小写 z,它按共享范围标记。大小写不是任选一种的拼写:同一目录先后被不同容器用 Z 重新标记,可能让之前的容器失去访问权限;改成 z 则扩大了可共享范围,必须符合原来的隔离设计。
当前 Compose 的长格式也有 bind.selinux 的 z、Z 设置。直接使用 Docker CLI 时,-v 可表达这类标签选项,--mount 本身不能设置 SELinux 重新标记。Docker Swarm 服务的挂载选项另有适用限制,不应把本机 Compose 的配置直接套过去。
这些选项会改变宿主机真实文件的标签,容器退出后影响仍可能保留。仅选择专供该应用使用的目录,不要对整个 /home、/usr 或系统根目录加 Z;这可能破坏宿主机上其他程序的访问。
修改挂载后,需要让目标容器采用新配置
变更前保存原 Compose 配置、目录内容、属主权限、安全上下文及相关 SELinux 文件上下文策略。确认哪些容器和宿主机服务正在共享该目录,安排允许中断的窗口。
编辑配置不会直接改变现有容器的挂载设置。按项目已有发布流程让目标服务重建容器并采用新挂载;Compose up 会在服务配置变化时停止并重建对应容器,单纯 restart 不能替换创建时的挂载配置。先核对服务范围、镜像和依赖,避免为一个目录问题顺带更新其他服务。
重建过程中应用会短暂停止,容器可写层中的临时文件也不能当作持久数据保留。不要删除数据卷或清空宿主目录来促使重建。标签修正之后,仍用原先约定的应用用户运行服务。
验收时一起检查共享方
从应用正常入口重复此前失败的读写操作,确认实际使用的是预期挂载,最近没有对应的新 AVC 拒绝,相关容器及宿主服务也能按原设计访问目录。仅看到容器启动成功,还不能证明文件创建、后续上传或后台任务已经恢复。
若访问仍失败,回到具体拒绝项和普通权限,不连续叠加权限放宽、标签变更和关闭 SELinux。恢复原配置并重建,只能撤回容器配置;删掉 :Z 不会自动还原已经改过的宿主机标签。标签恢复应根据保存的上下文和发行版策略工具处理,保留应用既有的自定义映射。新旧标签都无法恢复已经写入或删除的数据,数据恢复需单独依据备份执行。


