SELinux 拦截导致“Permission denied”时,应优先使用 -v /host:/cont:Z(独占)或 :z(共享)挂载选项自动重标上下文;若不可改命令,则用 semanage fcontext -a -t container_file_t 配置永久策略并 restorecon -Rv 生效,禁用 SELinux 仅限测试。
直接用 docker run -v 挂载宿主机目录到容器,在启用了 SELinux 的系统(比如 CentOS 7/8、RHEL、Fedora)上,大概率会遇到“Permission denied”——不是权限数字没对上,而是 SELinux 的安全上下文拦住了访问。
容器启动失败或报错类似:
mkdir: cannot create directory '/data': Permission deniedCan't create test file /var/lib/mysql/...
open_basedir restriction(实际是上下文拒绝)根本原因:Docker 默认不允许容器进程访问宿主机目录的 SELinux 上下文标签(如 system_u:object_r:default_t:s0),除非显式授权。
只需在 -v 参数末尾加一个冒号后缀,就能让 Docker 自动重标上下文:
:z —— 容器内多个进程共享该目录(多容器读写同一路径时用)例如:docker run -v /host/data:/app:data:z nginx
:Z —— 目录只供当前容器独占使用(更安全,默认推荐)例如:docker run -v /host/conf:/etc/nginx:Z nginx
注意::z 和 :Z 是小写字母 z,不是数字 2 或字母 Z 的大小写混用。Docker 会自动调用 chcon 修改宿主机目录的上下文为 container_file_t 或类似类型,并设置 relabel=yes。
如果不能改启动命令(如编排文件已固化),可手动调整宿主机目录的 SELinux 标签:
ls -Z /host/data
sudo chcon -Rt container_file_t /host/data
sudo semanage fcontext -a -t container_file_t "/host/data(/.*)?"再执行:sudo restorecon -Rv /host/data
⚠️ 不建议直接关闭 SELinux(setenforce 0 或改配置),这等于放弃一层关键防护。生产环境应优先适配,而非绕过。
结合常见场景给出几个关键提醒:
./config)在 :z/:Z 下无效no_root_squash 并配合 context=... mount 选项):Z 后,宿主机上该目录的原始上下文会被覆盖;若后续要从非容器进程访问,可能需要重新 restorecon
:z/:Z 行为与 Docker 一致,但某些旧版本需额外加 --security-opt label=type:container_file_t