强制性文件系统只读挂载是最底层防线,通过内核拦截写系统调用返回EROFS错误,确保配置文件、TLS证书、静态资源、只读数据集等不被篡改;需分层实施卷级只读(:ro)与根文件系统只读(--read-only),并配合tmpfs或可写volume开放必要路径。

强制性文件系统只读挂载,是保障静态资产(如配置文件、证书、HTML/CSS/JS、模型权重等)不被篡改、覆盖或意外写入的最底层防线。它不依赖应用逻辑、不靠权限控制、不仰仗进程身份,而是由内核在挂载时直接拦截所有写系统调用,返回 EROFS 错误——从机制上切断写入可能。
哪些静态资产必须设为只读
不是所有文件都适合只读,但以下几类一旦写入即意味着异常或风险:
- 配置文件:nginx.conf、app.yaml、log4j2.xml 等,运行时修改易引发服务错乱
- TLS 证书与私钥:server.crt、private.key、ca-bundle.pem,被覆盖将导致 HTTPS 中断或中间人风险
- 前端静态资源:/usr/share/nginx/html 下的 HTML、JS、CSS、图片,CI/CD 构建后应冻结内容
- 只读数据集:地理编码库、词典、预训练模型权重(.bin/.safetensors),体积大、更新频次低、严禁运行时变更
两种层级的只读保护要配合使用
单一挂载点只读 ≠ 全局安全。需分层实施:
-
卷级只读(推荐首选):对 bind mount 或 named volume 显式加
read_only: true或:ro,保护特定路径。例如:- ./certs:/etc/tls:ro -
容器根文件系统只读(增强基线):启动时加
--read-only,让整个/只读;再用--tmpfs或-v显式开放必需可写路径(如/tmp、/run),未声明路径一律不可写
配置要点与避坑提醒
只读不是加个 :ro 就万事大吉,常见失效原因:
- 应用默认在挂载目录下创建
cache/、tmp/或日志文件 → 必须把这类路径分离到独立tmpfs或可写 volume - 宿主机文件属主为
root:root,而容器内进程 UID 是1001→ 即使只读,仍因无读权限报Permission denied→ 需提前chown或在 Pod/Compose 中配fsGroup - 同一目标路径混用
:ro和:rw挂载 → Docker 直接拒绝启动,报 “duplicate mount point” - NFS/CephFS 等网络存储 → 容器侧设
read_only: true不够,服务端导出选项(如 NFS 的ro)也必须同步启用
验证是否真正生效的三步法
配置完别只信日志,动手验证:
- 进容器执行
mount | grep " /path/to/mount ",确认输出含ro,(如ro,relatime) - 尝试写入:
echo test > /etc/nginx/nginx.conf或touch /usr/share/nginx/html/test→ 应明确报错Read-only file system - 检查进程视角:
find /proc/1/root/etc/nginx -type f -name "*.conf" -exec ls -l {} \;,确认文件属主/权限与容器 UID 匹配且可读











