核心是区分服务级(read_only: true)与卷级(:ro或read_only: true)只读控制:前者使整个根文件系统只读,需配合tmpfs挂载临时目录;后者仅限制特定挂载点,适用于配置、证书等静态资源保护。
在 docker compose 中启用只读文件系统,核心是区分两种不同层级的只读控制:一种是**整个容器根文件系统只读**(用 read_only: true 服务级配置),另一种是**对特定挂载卷设为只读**(用 read_only: true 或 :ro 卷配置)。两者作用范围和使用场景不同,不能混用或替代。
服务级 read_only:让整个容器根文件系统只读
该配置作用于容器运行时的 rootfs 层,使除 tmpfs、/proc、/sys 等内核虚拟文件系统外的所有路径默认不可写。这是最严格的只读保护方式。
必须配合 tmpfs 挂载,否则容器会因无法写入 /tmp、/run、/var/run 等临时目录而启动失败。
- 在
services下直接声明read_only: true - 为必要可写路径显式添加
tmpfs挂载(如/tmp、/run、/var/run) - 确保应用不依赖写入镜像层中的任何路径(如
/app、/usr/local/bin)
示例:
services:
nginx:
image: nginx:alpine
read_only: true
tmpfs:
- /tmp
- /run
- /var/run
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro
- nginx-logs:/var/log/nginx
卷级 read_only:仅限制特定挂载点
这是更常用、更灵活的方式,只对 bind mount 或 named volume 的某个挂载目标路径设为只读,不影响容器其他路径。适用于保护配置、证书、静态资源等。
支持两种等效写法:
-
短语法:在 volume 字符串末尾加
:ro,例如- ./config:/etc/nginx:ro -
长语法:显式声明
read_only: true,可读性更强,推荐用于生产环境
示例(长语法):
volumes:
- type: bind
source: ./config
target: /etc/nginx
read_only: true
- type: bind
source: ./certs
target: /etc/ssl
read_only: true
关键注意事项
只读配置生效的前提是应用行为与挂载策略匹配。常见踩坑点包括:
- 日志路径被挂载为只读,但应用试图往里写日志 → 启动失败或静默崩溃
- 应用尝试在只读挂载目录中创建 PID 文件、socket 文件或锁文件 → 权限拒绝
- 未区分
read_only: true(服务级)和read_only: true(卷级),误以为设了卷只读就等于整个容器只读 - 使用
read_only: true服务级配置却没配tmpfs→ 容器无法初始化临时目录,根本起不来
验证是否生效
启动后进入容器测试写入行为是最直接的验证方式:
docker-compose exec nginx sh -c 'echo test > /etc/nginx/test.txt' # 应返回:sh: can't create /etc/nginx/test.txt: Read-only file system <p>docker-compose exec nginx sh -c 'echo test > /tmp/test.txt'</p><h1>若配置了 tmpfs,则应成功;若没配,也会报错</h1><p>
也可用 mount | grep "ro," 查看挂载项是否含 ro 标志。


















