只读根的思路
--read-only 把容器的根文件系统挂成只读:容器内进程无法改写镜像层里的文件,服务被入侵后也难以把工具写进系统目录做持久化。无状态服务适配起来最省力,但多数应用仍需若干可写目录(临时文件、pid、socket、缓存),做法是用 tmpfs 或具名卷把这几处单独放开,其余部分保持只读。
基本信息
| 参数 | docker run --read-only |
|---|---|
| 配套 | --tmpfs /tmp、--tmpfs /run 放开必要可写目录 |
| 取值核对 | inspect 的 HostConfig.ReadonlyRootfs 为 true |
| 验证 | 容器内 touch /probe 应返回只读失败 |
典型使用场景
- 无状态 Web 服务加固:镜像层完全只读,运行时不需要写入自身目录
- 缩小入侵面:被攻破后无法往系统目录写后门与脚本
- 发布一致性核对:只读环境能快速暴露「依赖写本地文件」的隐患
- 配合非 root 用户使用:权限与文件系统两道约束叠加
- 安全基线落地:作为容器标准配置的一部分批量开启
启动与验证
启动与验证
# 只读根文件系统,另开两处可写目录
docker run -d --name web --read-only --tmpfs /tmp:rw,size=64m --tmpfs /run nginx:1.27-alpine
# 验证根文件系统确实不可写
docker exec web sh -c 'touch /probe' || echo 'readonly ok'
# 核对只读配置是否生效
docker inspect -f '{{.HostConfig.ReadonlyRootfs}}' web
# 应用报错提示某个目录需要写时,逐个补 tmpfs 或卷常见放开的目录
| 目录 | 为什么要写 | 处理方式 |
|---|---|---|
| /tmp | 应用生成的临时文件 | --tmpfs /tmp:rw,size=64m 限制大小 |
| /run | pid 文件与 unix socket | --tmpfs /run |
| 缓存目录 | 如 nginx 的 cache 与 proxy_temp | tmpfs 或具名卷 |
| 应用数据目录 | 需要长期保留的数据 | 具名卷,注意属主与权限 |
常用适配路径是先把服务按只读启动,跟着报错逐个补可写目录,比事先猜需要哪些目录更快。
写日志到本地文件的应用要先改成标准输出或挂卷,否则开启只读后启动阶段就会失败。
只读根与特权模式语义冲突:--privileged 的容器往往要改写系统路径,两者同时使用会出现难以解释的失败,加固前先确认服务不依赖特权。