Docker容器默认无权访问宿主机任何设备节点,必须通过--device显式挂载并设权限;辅以--cap-drop、--security-opt和cgroups device控制器实现细粒度隔离。

在 Docker 中限制容器对主机硬件设备(如 GPU、USB 设备、声卡、磁盘等)的访问,主要通过 --device 参数显式授权,配合 --cap-drop、--security-opt 和 cgroups v1/v2 的 device controller 进行细粒度控制。默认情况下,容器**无权访问任何宿主机设备节点**(/dev/ 下),必须明确挂载才可使用。
用 --device 显式挂载并限制权限
这是最常用且推荐的方式:只挂载容器真正需要的设备,并可指定读写权限。
-
基础语法:
docker run --device <host-path>:<container-path>[:<mode>] -
:r表示只读(如--device /dev/sda:/dev/sda:r),:w表示只写,:rw(默认)表示读写 - 不加
:r/:w时,容器内设备节点拥有与宿主机相同的权限位,但实际能否操作还取决于容器进程的 capability 和 cgroups 限制 - 例如,仅允许容器读取 USB 摄像头:
docker run --device /dev/video0:/dev/video0:r ubuntu:22.04 ls -l /dev/video0
用 --cap-drop 和 --security-opt 阻断设备相关能力
即使挂载了设备,也可通过移除 Linux capability 或启用安全策略进一步限制行为。
-
--cap-drop=SYS_ADMIN:禁用容器内执行mknod、mount、修改设备权限等高危操作,防止其自行创建或篡改设备节点 -
--security-opt=no-new-privileges:true:阻止容器内进程通过execve获取额外权限(如 setuid 二进制),增强设备访问隔离性 -
--cap-drop=ALL --cap-add=CHOWN,DAC_OVERRIDE等组合可用于最小化特权,但需谨慎评估应用实际需求
用 cgroups device 控制器做白名单级过滤(高级)
适用于 Docker daemon 启用了 cgroups v1 或 v2 且需要更底层控制的场景(如多租户环境)。Docker 本身不直接暴露 device cgroup 配置,但可通过以下方式生效:
- 在
daemon.json中启用"default-runtime": "runc"并确保系统支持 device cgroup(检查/sys/fs/cgroup/devices/是否存在) - 启动容器时传入
--cgroup-parent指向预设的 device 白名单 cgroup(需提前用cgcreate+cgset配置) - 例如,只允许读取
/dev/null和/dev/zero,禁止访问所有块设备:cgset -r devices.allow="c 1:3 rwm" mydevcg(c 1:3是/dev/null),再运行docker run --cgroup-parent=mydevcg ... - 注意:Docker CLI 不提供原生
--device-cgroup-rule参数;该功能更常见于直接使用 runc 或 Kubernetes DevicePlugin 场景
避免常见误区
一些看似“限制”实则无效或危险的做法需避开:
-
不要挂载整个
/dev(如-v /dev:/dev):这会暴露全部设备节点,极大提升攻击面,且绕过所有 device cgroup 控制 -
不要依赖镜像内
/dev内容:容器启动时/dev由 init 进程(如devtmpfs)动态生成,与镜像无关;设备访问权限完全取决于挂载和 cgroup 配置 -
GPU/USB 等特殊设备需额外驱动支持:仅挂载设备节点不够,还需宿主机安装对应驱动(如 nvidia-driver)、容器内有兼容库(如
nvidia-container-toolkit),否则设备不可用

















