直接在挂载路径后加:ro是最有效防护,但需注意三点:默认可写,故必须显式声明;/etc等目录含运行时需更新文件,不可整目录只读;只读仅为第一道防线,须叠加tmpfs、最小权限与非root运行。

直接在挂载路径后面加 :ro 就行,但必须注意三个关键点:默认是可写、敏感目录不能硬套只读、只读只是起点。
明确写 :ro 才生效
Bind Mount 默认就是读写(:rw),哪怕不写也等同于可写。想只读,必须显式加上 :ro:
-
docker run -v /host/conf:/etc/app:ro nginx—— 正确,/etc/app 在容器内只读 -
docker run -v /host/conf:/etc/app nginx—— 错误,默认可写,容器能删改配置 -
docker run -v /host/conf:/etc/app:RO nginx—— 错误,大小写敏感,必须小写 ro
避开 /etc 等伪只读陷阱
有些目录看着是配置,实际运行时要动态更新文件(比如 /etc/resolv.conf、/etc/mtab、/etc/hostname)。整目录挂只读会直接导致容器启动失败或服务异常:
- 不要
-v /etc:/etc:ro—— 容器大概率起不来 - 应拆细:只挂真正静态的部分,例如
-v /host/app.conf:/etc/app/app.conf:ro - 动态文件用其他方式注入(如
--sysctl、--dns、或通过 entrypoint 生成)
配合 tmpfs 和最小权限才落地
只读挂载本身防不住所有风险。攻击者若逃逸进容器,仍可能利用宿主机路径做跳板(比如挂了 /root/.ssh 却没设只读,密钥就被覆盖):
- 敏感路径必须加 :ro,例如
-v /host/secrets:/run/secrets:ro - 需要临时写入的目录(如
/tmp、/var/run)优先用tmpfs:--tmpfs /tmp:rw,size=64m - 容器用户尽量非 root,再配合只读挂载,形成权限叠加防护
Docker Compose 写法一致
在 docker-compose.yml 中同样用 :ro,语法更清晰:
volumes: - ./config:/app/config:ro - /opt/data:/data:ro
注意路径必须是绝对路径(/opt/data),相对路径(./config)只在 compose 文件所在目录解析,且需提前存在。


















