--privileged=false 无效,因该参数不接受值,会被Docker静默忽略;正确做法是不加此参数,并配合--cap-drop=ALL、--user、--read-only等强化限制。

直接结论:--privileged=false 不是“禁止”特权的开关,而是 Docker 的默认行为;你根本不需要显式写它——写了也无效,Docker 会忽略。
为什么 --privileged=false 没有任何实际作用
Docker 的 --privileged 参数是布尔型 flag,只接受存在(启用)或不存在(禁用)两种状态。它没有“设为 false”的语法支持:--privileged=false 在 CLI 中会被 Docker 解析为传递一个字符串值 false 给 --privileged,而该参数根本不接受值,因此该参数被静默丢弃,等效于没写。实测中运行 docker run --privileged=false alpine id,容器仍以非特权模式启动,不是因为 “false 生效”,而是因为 --privileged 根本没被触发。
- 正确禁用特权的方式就是——不加
--privileged参数 - 加了
--privileged(无值)才真正启用特权模式 - 加
--privileged=true或--privileged=false都属于误用,Docker CLI 会警告或忽略
真正能强制限制容器权限的替代方案
想让容器彻底无法获得主机设备、内核模块、网络栈重配置等能力,靠“不写 --privileged”只是基础。你还必须组合以下约束:
- 显式禁用危险 capabilities:
--cap-drop=ALL --cap-add=NET_BIND_SERVICE(按需加回极少数必要能力) - 使用非 root 用户运行:
--user 1001:1001或在 Dockerfile 中声明USER 1001 - 挂载文件系统为只读:
--read-only,配合--tmpfs /run --tmpfs /tmp提供必要可写空间 - 禁用 IPC、PID、UTS 命名空间共享:
--ipc=private --pid=private --uts=private - 限制资源访问:
--cgroup-parent=docker-slim.slice(配合 systemd cgroup v2)
检查容器是否意外获得特权的快速验证方法
进入运行中的容器后,执行以下命令可快速判断是否落入特权陷阱:
ls /dev/sd* # 能列出宿主机块设备?→ 极大概率已特权 mount -t debugfs none /sys/kernel/debug # 成功挂载?→ 拥有 SYS_ADMIN cat /proc/1/cgroup | grep devices # devices:/docker/... → 未被限制设备访问 capsh --print | grep cap_sys_admin # 输出含 cap_sys_admin → 危险能力残留
只要其中任意一项返回非空结果,说明当前容器权限远超安全基线,--privileged 虽未显式启用,但可能通过 --cap-add=SYS_ADMIN 或 --security-opt seccomp=unconfined 等方式变相绕过。
最容易被忽略的隐性特权入口
很多人以为“没加 --privileged 就安全了”,却忽略了三个高危但隐蔽的配置点:
-
--device=/dev/ttyUSB0:挂载单个设备等价于开放对应硬件控制权,无需特权即可完成部分逃逸链 -
--volume /:/host-root:rshared:rshared 挂载使容器内 mount 事件传播回宿主机,配合mount --bind可覆盖关键路径 -
--security-opt apparmor=unconfined或seccomp=unconfined:直接卸载所有 syscall 过滤层,能力管控形同虚设
这些选项不会触发 “Privileged mode enabled” 日志,但实际效果与 --privileged 高度重叠——它们才是真正需要逐条审计的“静默特权”。











