启用--read-only可使容器根分区只读,但需同步为/tmp、/run等路径挂载tmpfs,并严格控制可写卷路径与权限,结合drop能力、非root运行等最小权限措施构成纵深防御。

直接加 --read-only 就能让容器根分区(/)变成只读,这是防止运行时被篡改最直接有效的手段。但它不是“开箱即用”的独立方案——必须同步为关键路径提供受控的可写空间,否则应用大概率启动失败或静默崩溃。
启用只读根并确认生效
启动容器时加上 --read-only 参数即可:
docker run --read-only -it alpine sh- 进容器后执行
mount | grep "on / type",输出中应含ro字样 - 尝试
touch /test或echo 1 > /etc/hostname,应报错Read-only file system - 也可用
docker inspect -f '{{.HostConfig.ReadonlyRootfs}}'查看是否返回true
为必需路径挂载 tmpfs(内存临时卷)
大多数应用依赖 /tmp、/run、/var/run 等路径写 PID、socket、锁或临时解压包。这些路径在只读根下默认不可写,必须显式挂载 tmpfs:
-
--tmpfs /tmp:rw,size=10M:通用临时目录,多数程序默认使用 -
--tmpfs /run:rw,size=5M和--tmpfs /var/run:rw,size=5M:nginx、supervisord、systemd-init 等必备 -
--tmpfs /var/log:rw,size=2M:仅当应用坚持写本地日志;更推荐统一改用 stdout/stderr 输出
tmpfs 数据驻留内存、容器退出即清空,不落盘、无残留,天然契合“临时性”语义,也避免持久卷带来的权限扩大风险。
按需挂载可写数据卷(严格限定路径与权限)
只有真正需要持久化或跨容器共享的数据,才应挂载可写卷,且必须显式声明路径和权限:
- 上传目录:
-v upload-data:/app/uploads:rw(命名卷,推荐) - 数据库或缓存数据:
-v redis-data:/data:rw - 证书、配置、静态资源:
-v cert-volume:/etc/tls:ro(务必用:ro明确禁止写入) - 禁用 bind mount 宿主机敏感路径(如
/etc、/root),尤其避免:z或:ZSELinux 标签,除非完全理解其提权后果
未显式挂载的任何路径(哪怕只是 /app/logs)都继承全局只读属性,不会自动获得写权限。
协同最小权限机制构成纵深防御
只读根本身不能单独防逃逸,它必须和其他最小权限措施联动才能显著压缩攻击面:
- 丢弃非必要能力:
--cap-drop=ALL --cap-add=NET_BIND_SERVICE - 禁止提权:
--security-opt no-new-privileges - 强制非 root 用户运行:
--user 1001:1001,并在 Dockerfile 中固化USER指令 - Kubernetes 场景下,在
securityContext统一设置:readOnlyRootFilesystem: true、runAsNonRoot: true、capabilities.drop - 镜像构建阶段就清理缓存和调试工具:
RUN apt clean && rm -rf /var/lib/apt/lists/*


















