启用--read-only是防止nginx容器配置被篡改的最有效防线,但必须配合只读挂载配置目录、禁用符号链接与通配加载、全局location屏蔽点文件、清理备份文件、降权运行及能力裁剪才能真正生效。

直接启用只读根文件系统(--read-only)是防止黑客攻破 Nginx 容器后篡改主配置文件最有效的一道防线,但它必须配合权限控制、路径隔离与运行时防护才能真正生效——不是“设了就安全”,而是“设对才可靠”。
让根文件系统真正不可写
启动容器时必须显式添加 --read-only 参数:
docker run --read-only --name nginx-secure -p 80:80 -v /host/conf:/etc/nginx:ro nginx:alpine- 验证是否生效:
docker exec nginx-secure mount | grep "on / type",输出应含ro标志 - 进入容器执行
echo "test" > /etc/nginx/nginx.conf,必须报错Read-only file system
严格保护配置目录的挂载方式
Nginx 主配置和子配置都必须通过只读绑定挂载,且禁止通配或宽泛路径:
- 用长语法明确声明只读:
volumes: [{type: bind, source: /host/nginx/conf, target: /etc/nginx, read_only: true}] - 避免挂载父目录(如
/host),只挂载最小必要路径(如/host/nginx/conf) - 禁用
include /etc/nginx/conf.d/*.conf这类泛加载;改用显式列表:include /etc/nginx/conf.d/app.conf; - 宿主机上对应路径权限设为
640,属主root:root,确保即使容器内提权也无法绕过内核只读检查
切断运行时动态覆盖与泄露路径
只读磁盘不是终点,还需堵住 HTTP 访问、符号链接、备份文件等绕过渠道:
- 在
http块中全局加:location ~ /\. { deny all; },防止通过 URL 请求/etc/nginx/nginx.conf - 清理所有备份文件(
.bak、.swp、~),或统一设为640 root:root,否则可能被include指令意外加载 - 编译或镜像中禁用符号链接支持:
--without-http-symlinks,或挂载分区时加noexec,nosuid,nodev - 关闭
server_tokens on,隐藏版本号,减少攻击者针对性利用
降权运行 + 能力裁剪形成纵深防御
即使根只读,若容器以 root 运行并保留高权限能力,仍可能卸载挂载、逃逸或干扰防护机制:
- 创建专用用户:
useradd -r -s /sbin/nologin nginx,并在nginx.conf开头设user nginx; - Docker 启动加
--user 1001:1001(与 UID/GID 对齐),彻底规避 root 权限滥用 - 丢弃全部能力:
--cap-drop=ALL,仅按需添加--cap-add=NET_BIND_SERVICE - 证书、静态资源等敏感挂载一律用
:ro,日志路径单独挂载可写卷(如-v nginx-log:/var/log/nginx:rw)
不复杂但容易忽略:只读根只是起点,真正的防护在于把配置路径、挂载行为、运行身份和 HTTP 层响应全部纳入同一套最小权限逻辑里。每少一个例外,攻击面就小一分。











