bigywater.tech
Docker · 50

设备透传:--device 与 cgroup 设备白名单

怎么把宿主机的设备交给容器用?--device 的 r/w/m 权限有什么用?容器里 mknod 出来的设备文件为什么打不开?这篇用 /dev/fuse、/dev/net/tun、/dev/loop7 实测。

ENOENT → 10:229
默认容器里没有 /dev/fuse;加 --device 后出现,主次设备号 10:229
:r → EPERM
以只读权限放进来的设备,用写方式打开得到 EPERM
mknod 成功但 EPERM
容器里自己 mknod 的设备文件,没有设备 cgroup 规则时打不开

--device

实测 · 本机执行输出
  默认:
    /dev/fuse:不存在;O_RDONLY→ENOENT;O_WRONLY→ENOENT
    /dev/net/tun:不存在;O_RDONLY→ENOENT;O_WRONLY→ENOENT
    /dev/loop7:不存在;O_RDONLY→ENOENT;O_WRONLY→ENOENT
    /dev/zero:crw-rw-rw- 1:5;O_RDONLY→成功;O_WRONLY→成功
  --device /dev/fuse --device /dev/net/tun:
    /dev/fuse:crw-rw-rw- 10:229;O_RDONLY→成功;O_WRONLY→成功
    /dev/net/tun:crw-rw-rw- 10:200;O_RDONLY→成功;O_WRONLY→成功
    /dev/loop7:不存在;O_RDONLY→ENOENT;O_WRONLY→ENOENT

只有显式 --device 的设备才会出现在容器的 /dev 里;没指定的(如 loop7)仍然不存在。设备在容器里的路径可以改名,主次设备号不变。

权限后缀

实测 · 本机执行输出
  --device /dev/loop7:/dev/mydisk:r(只读):
    /dev/mydisk:brw-rw-rw- 7:7;O_RDONLY→成功;O_WRONLY→EPERM
    /dev/loop7:不存在;O_RDONLY→ENOENT;O_WRONLY→ENOENT
  --device /dev/loop7:/dev/mydisk:rw(读写,不能 mknod):
    /dev/mydisk:brw-rw-rw- 7:7;O_RDONLY→成功;O_WRONLY→成功
  --device /dev/zero:/dev/myzero:
    /dev/myzero:crw-rw-rw- 1:5;O_RDONLY→成功;O_WRONLY→成功

路径后面的 :r、:rw 是设备 cgroup 的权限:只读时,以写方式打开设备返回 EPERM。我这里只试了打开(open),没有真正读写块设备。

mknod 不等于能用

实测 · 本机执行输出
  默认(有 MKNOD capability):mknod 退出码 0 | /tmp/myfuse:crw-r--r-- 10:229;O_RDONLY→EPERM;O_WRONLY→EPERM
  加 --device-cgroup-rule 'c 10:229 rwm':mknod 退出码 0 | /tmp/myfuse:crw-r--r-- 10:229;O_RDONLY→成功;O_WRONLY→成功
  加 --device-cgroup-rule 'c 10:229 r'(只读):mknod 退出码 0 | /tmp/myfuse:crw-r--r-- 10:229;O_RDONLY→成功;O_WRONLY→EPERM

默认容器有 MKNOD capability,能创建设备文件;但设备 cgroup 没有放行这个主次设备号时,open 一律 EPERM。--device-cgroup-rule 'c 10:229 rwm' 放行后才能打开。这也是为什么 --privileged 之外,想用某类设备时优先 --device。

inspect 里的样子

实测 · 本机执行输出
  HostConfig.Devices = [{"PathOnHost":"/dev/fuse","PathInContainer":"/dev/fuse","CgroupPermissions":"rwm"},{"PathOnHost":"/dev/loop7","PathInContainer":"/dev/mydisk","CgroupPermissions":"r"}]
  HostConfig.DeviceCgroupRules = ["c 10:229 rwm"]

HostConfig.Devices 记录宿主路径、容器路径和权限,DeviceCgroupRules 记录规则字符串。

分步演示

设备直通
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。设备是 Docker Desktop 虚拟机里已有的:/dev/fuse、/dev/net/tun、/dev/loop7(块设备,只做 open / close,没有读写数据);打开测试用 Python os.open;每种配置运行一次;实验后已删除容器和镜像
    • 没有验证:真实设备(GPU、串口、USB)的直通、--device 对设备节点属主与模式的影响、cgroup v1 devices 子系统、Docker Desktop 以外的 Linux 宿主机的设备、fuse 文件系统的实际挂载
    京ICP备2026067502号-1京公网安备11010502063487号