mount -o bind,ro 是保护静态资源目录最轻量可控的方式,需配合 bind 使用以实现路径级只读,不修改权限、不影响 stat,但不递归子挂载;chattr +i 则作用于文件本体,二者机制冲突不可混用。

mount -o ro 临时挂载静态资源目录
直接用 mount -o ro 是最轻量、最可控的方式,适合 Web 静态资源(如 /www/wwwroot/example.com/html)这类明确不需运行时写入的路径。它不改文件权限、不依赖用户身份,内核在 VFS 层就拦截所有 write 系统调用。
操作步骤:
- 确认目标目录当前未被其他进程独占占用(
fuser -v /path/to/dir检查) - 执行
sudo mount -o bind,ro /www/wwwroot/example.com/html /www/wwwroot/example.com/html—— 注意:必须用bind+ro组合,单纯mount -o ro /dev/xxx /path要求该路径本身是一个独立挂载点 - 验证:
touch /www/wwwroot/example.com/html/test应报错Read-only file system
⚠️ 常见坑:漏掉 bind 参数会导致命令失败或挂载错位;若目录下已有子挂载(如 /uploads 单独挂了 tmpfs),ro 不会穿透到子挂载,它们仍可写。
/etc/fstab 永久生效但必须谨慎处理子目录
把 bind,ro 写进 /etc/fstab 才能开机自动加固,但这里最容易出问题的是“递归性”误解——bind 挂载不自动递归子目录,更不会覆盖已存在的子挂载。
正确写法示例(以保护静态根目录,同时放行上传目录):
none /www/wwwroot/example.com/html none bind,ro 0 0 none /www/wwwroot/example.com/html/uploads none bind,rw 0 0
关键点:
- 第一行用
none作设备名,表示 bind 挂载;bind,ro是核心选项 - 第二行显式把
uploads单独再 bind 一次,并加rw,覆盖前一行的只读限制 - 两行都必须存在,且顺序不能颠倒(后挂载的会覆盖前挂载的同路径)
执行 sudo mount -a 测试,失败时看 dmesg | tail —— 常见错误是 uploads 目录不存在或权限不足,导致 rw 挂载失败,进而整个 fstab 加载中断。
chattr +i 和 mount -o ro 别混着用
有人想“双重保险”,给目录先 chattr +i 再 mount -o ro,结果发现连 ls 都卡住,或者容器启动失败。这是因为 +i 是文件系统属性级锁定,而 bind,ro 是 VFS 层挂载控制,二者作用机制冲突,且 +i 会让内核拒绝几乎所有元数据操作(包括 stat),反而干扰 Web 服务器正常遍历目录。
该用哪个?
- 保护整站静态根(含大量 .html/.js/.css)→ 选
mount -o bind,ro,运维友好、可逆、不影响 stat - 保护单个关键配置(如
/etc/nginx/nginx.conf)→ 选chattr +i,防 root 误覆盖 - 保护证书私钥(
/etc/ssl/private/server.key)→ 必须chattr +i,因为即使只读挂载也无法阻止 root 用echo覆盖文件内容
简单记:挂载级只读管“路径访问行为”,属性级不可变管“文件本体状态”。
Docker/K8s 中等效做法是 :ro 卷挂载
容器场景下,mount -o ro 不适用,但原理一致:通过只读卷挂载切断写入通路。关键是别只写 :ro 就完事,得确认宿主机源路径本身没被其他容器或进程写入。
典型配置:
services:
web:
image: nginx
volumes:
- ./html:/usr/share/nginx/html:ro
- ./uploads:/usr/share/nginx/html/uploads:rw注意:
-
:ro是 Docker 引擎识别的只读标记,不是 Linuxmount的ro选项 - 如果宿主机
./html下的uploads是软链或 bind 挂载,容器内:ro无法限制其目标路径的写行为 - K8s 中对应的是
volumeMounts.readOnly: true,但 ConfigMap/Secret 默认就是只读,无需额外设
真正难的从来不是加只读,而是厘清“哪些路径真静态、哪些看着静态实则被运行时代码动态生成”。比如某些 CMS 的 /themes 目录,表面是模板,实际插件会往里写缓存文件——这种地方加了只读,服务就直接 500。先跑一遍 inotifywait -m -e create,modify,delete /path 观察真实写入模式,再动手。


















