<p>Docker本身不直接提供“设备白名单”配置命令,而是通过Linux cgroup v1 device controller实现,使用--device-cgroup-rule参数注入四字段规则(type major minor access),如c 1:3 rwm,严格控制容器对/dev下设备的open、read、write及mknod权限,且默认根白名单为a : rwm,新增规则为追加而非覆盖。</p>

Docker本身不直接提供“设备白名单”配置命令,但底层通过 Linux 的 cgroup v1 device controller(设备 cgroup)实现对容器可访问设备文件的精细控制。这种限制作用于 /dev 下的字符设备(c)、块设备(b)或全部设备(a),决定容器能否 open、read、write 或执行 mknod 创建设备节点。
关键点在于:Docker 通过 --device-cgroup-rule 参数将规则注入设备 cgroup 白名单,而非修改容器内文件或运行时挂载。
设备白名单规则格式说明
每条规则是空格分隔的四字段字符串:<type> <major> <minor> <access>
-
type:a(all)、b(block)、c(char) -
major/minor:主/次设备号,可用*表示任意 -
access:组合权限,r(读)、w(写)、m(允许mknod)
例如:
-
c 1:3 rwm→ 允许对主1次3的字符设备读、写、创建节点 -
a *:* r→ 允许读所有设备(危险,慎用) -
c *:* m→ 允许mknod任意字符设备(需配合--cap-add=SYS_MKNOD)
默认情况下,Docker 启动容器时,根设备 cgroup 的初始白名单是 a *:* rwm。你添加的规则会追加到该白名单中(不是覆盖),因此必须显式拒绝不需要的设备,才能真正限制。
配置步骤(以只允许访问 /dev/null 和 /dev/zero 为例)
-
确认目标设备号
在宿主机执行:ls -l /dev/null /dev/zero # 输出类似:crw-rw-rw- 1 root root 1, 3 May 8 22:00 /dev/null # crw-rw-rw- 1 root root 1, 5 May 8 22:00 /dev/zero # 主设备号都是 1,次设备号分别是 3 和 5
-
启动容器时添加设备白名单规则
docker run -it \ --device-cgroup-rule='c 1:3 rwm' \ --device-cgroup-rule='c 1:5 rwm' \ --device-cgroup-rule='a *:* r' \ # 允许读所有设备(基础权限) --device-cgroup-rule='a *:* w' \ # 允许写所有设备(基础权限) --device-cgroup-rule='c *:* m' \ # 允许 mknod 字符设备(如需动态创建) ubuntu:22.04
⚠️ 注意:上面最后三条是保留基础能力所必需的;若想严格禁止除指定外的所有设备操作,应改用拒绝式策略(见下文进阶用法)。
-
验证容器内是否受限
进入容器后尝试访问其他设备:ls -l /dev/sda # 若未放行,会显示 "No such file or directory" 或 permission denied mknod /tmp/test c 1 100 # 若无 'm' 权限或未放行 major:minor,会报 Operation not permitted
进阶:实现“仅允许指定设备,其余一律拒绝”
Docker 不支持 deny 类型规则,但可通过以下方式模拟:
- 启动容器时不加
a *:* rwm,而是逐条精确放行所需设备; - 确保容器不带
--privileged(否则绕过所有设备限制); - 避免使用
--cap-add=SYS_ADMIN或--cap-add=SYS_MKNOD(除非明确需要); - 可配合
--read-only或--tmpfs /dev减少设备节点暴露。
例如,只允许 /dev/null、/dev/zero、/dev/random:
docker run -it \ --device-cgroup-rule='c 1:3 rwm' \ # null --device-cgroup-rule='c 1:5 rwm' \ # zero --device-cgroup-rule='c 1:8 r' \ # random(通常只读) --device-cgroup-rule='c 1:9 r' \ # urandom(只读) ubuntu:22.04
此时容器无法 open /dev/tty、/dev/sdb 等未列明设备,也无法 mknod 任何新设备节点(因没加 m 权限且未开放 c *:* m)。
常见误区提醒
-
--device /dev/sda:/dev/sda是挂载宿主机设备文件,不等于放行设备访问权限;仍受设备 cgroup 规则约束。 -
--cap-add=SYS_MKNOD仅允许调用mknod()系统调用,但能否成功创建某设备,还取决于设备 cgroup 是否允许对应major:minor的m权限。 -
mknod创建的设备节点只是文件,真正访问硬件仍需内核驱动和设备 cgroup 许可。 - Docker Desktop(macOS/Windows)不支持设备 cgroup,该机制仅适用于 Linux 宿主机。
不复杂但容易忽略。


















