上次我检查时,Docker没有任何方法让容器访问主机串行或USB端口。有什么技巧可以做到吗?


当前回答

我想扩展已经给出的答案,包括对未使用/dev/bus/usb捕获的动态连接设备的支持,以及在使用Windows主机和boot2docker VM时如何使其工作。

如果你正在使用Windows,你需要在VirtualBox管理器中为你想要Docker访问的设备添加任何USB规则。为此,您可以通过以下命令停止虚拟机:

host:~$ docker-machine stop default

打开VirtualBox管理器,根据需要添加带有过滤器的USB支持。

启动boot2docker虚拟机:

host:~$ docker-machine start default

由于USB设备连接到boot2docker虚拟机,因此需要从该机器运行命令。打开虚拟机的终端,运行docker run命令:

host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash

注意,当命令像这样运行时,只有以前连接的USB设备将被捕获。只有当您希望在容器启动后连接的设备上工作时,才需要volumes标志。在这种情况下,你可以使用:

docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash

注意,在某些情况下,我必须使用/dev而不是/dev/bus/usb来捕获像/dev/sg2这样的设备我只能假设对于/dev/ttyACM0或/dev/ ttyusb0这样的设备也是如此。

docker运行命令也可以在Linux主机上运行。

其他回答

我想扩展已经给出的答案,包括对未使用/dev/bus/usb捕获的动态连接设备的支持,以及在使用Windows主机和boot2docker VM时如何使其工作。

如果你正在使用Windows,你需要在VirtualBox管理器中为你想要Docker访问的设备添加任何USB规则。为此,您可以通过以下命令停止虚拟机:

host:~$ docker-machine stop default

打开VirtualBox管理器,根据需要添加带有过滤器的USB支持。

启动boot2docker虚拟机:

host:~$ docker-machine start default

由于USB设备连接到boot2docker虚拟机,因此需要从该机器运行命令。打开虚拟机的终端,运行docker run命令:

host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash

注意,当命令像这样运行时,只有以前连接的USB设备将被捕获。只有当您希望在容器启动后连接的设备上工作时,才需要volumes标志。在这种情况下,你可以使用:

docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash

注意,在某些情况下,我必须使用/dev而不是/dev/bus/usb来捕获像/dev/sg2这样的设备我只能假设对于/dev/ttyACM0或/dev/ ttyusb0这样的设备也是如此。

docker运行命令也可以在Linux主机上运行。

对于最新版本的docker,这就足够了:

docker run -ti --privileged ubuntu bash

它将允许访问所有系统资源(例如/dev)

在当前版本的Docker中,你可以使用——device标志来实现你想要的,而不需要访问所有的USB设备。

例如,如果你想在Docker容器中只使/dev/ttyUSB0可访问,你可以这样做:

docker run -t -i --device=/dev/ttyUSB0 ubuntu bash

如果你想在docker容器已经运行时动态地访问可以插入的USB设备,例如在/dev/video0上访问一个附加的USB摄像头,你可以在启动容器时添加一个cgroup规则。该选项不需要——特权容器,只允许访问特定类型的硬件。

步骤1

检查您想要添加的设备类型的设备主编号。您可以在linux内核文档中查找它。或者你可以检查你的设备。例如,要检查连接到/dev/video0的网络摄像头的设备主设备号,可以执行ls -la /dev/video0。结果如下:

crw-rw----+ 1 root video 81, 0 Jul  6 10:22 /dev/video0

其中第一个数字(81)是设备主设备号。一些常见的设备主号:

81: usb网络摄像头 188: usb到串行转换器

步骤2

在启动docker容器时添加规则:

添加——device-cgroup-rule='c major_number:* rmw'规则用于您想要访问的每种类型的设备 增加对udev信息的访问,这样docker容器就可以通过-v /run/udev:/run/udev:ro来获取usb设备上的更多信息 使用-v /dev:/dev将/dev卷映射到docker容器

总结

因此,要将所有usb网络摄像头和serial2usb设备添加到docker容器,请执行以下操作:

docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash

--device works until your USB device gets unplugged/replugged and then it stops working. You have to use cgroup devices.allow get around it. You could just use -v /dev:/dev but that's unsafe as it maps all the devices from your host into the container, including raw disk devices and so forth. Basically this allows the container to gain root on the host, which is usually not what you want. Using the cgroups approach is better in that respect and works on devices that get added after the container as started.

在Docker中访问USB设备而不使用——特权

这有点难粘贴,但简而言之,你需要获得你的角色设备的主编号,并将其发送到cgroup:

188是/dev/ttyUSB*的主编号,可以通过'ls -l'获得。你的系统和我的系统可能不同:

root@server:~# echo 'c 188:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow  
(A contains the docker containerID)

然后像这样启动你的容器:

docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64

如果不这样做,容器启动后任何新插入或重新启动的设备将获得一个新的总线ID,并且将不允许访问容器。