Ben*_*ley 171
有几种选择.首先,正如下面的@Mark所述,Docker 1.2.0版(2014/08发布)添加了一个--device
标志,用于在没有--privileged
模式的情况下访问USB设备:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Run Code Online (Sandbox Code Playgroud)
或者,假设您的USB设备可用于主机上的驱动程序等/dev/bus/usb
,您可以使用特权模式和卷选项将其安装在容器中.例如:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash
Run Code Online (Sandbox Code Playgroud)
Mar*_*ark 76
使用当前版本的Docker,您可以使用该--device
标志来实现您想要的功能,而无需访问所有USB设备.
例如,如果您只想/dev/ttyUSB0
在Docker容器中访问,则可以执行以下操作:
docker run -t -i --device=/dev/ttyUSB0 ubuntu bash
Run Code Online (Sandbox Code Playgroud)
rrp*_*lot 11
我想扩展已经给出的答案,包括支持未捕获的动态连接设备/dev/bus/usb
以及如何在使用Windows主机和boot2docker VM时使其工作.
如果您使用的是Windows,则需要为希望Docker在VirtualBox管理器中访问的设备添加任何USB规则.为此,您可以通过运行以下命令来停止VM:
host:~$ docker-machine stop default
Run Code Online (Sandbox Code Playgroud)
打开VirtualBox Manager并根据需要添加带有过滤器的USB支持.
启动boot2docker VM:
host:~$ docker-machine start default
Run Code Online (Sandbox Code Playgroud)
由于USB设备连接到boot2docker VM,因此需要从该计算机运行命令.使用VM打开终端并运行docker run命令:
host:~$ docker-machine ssh
docker@default:~$ docker run -it --privileged ubuntu bash
Run Code Online (Sandbox Code Playgroud)
注意,当命令像这样运行时,只会捕获以前连接的USB设备.只有在您希望在启动容器后才能使用连接的设备时,才需要使用卷标志.在这种情况下,您可以使用:
docker@default:~$ docker run -it --privileged -v /dev:/dev ubuntu bash
Run Code Online (Sandbox Code Playgroud)
注意,我不得不使用/dev
而不是/dev/bus/usb
在某些情况下捕获像这样的设备/dev/sg2
.我只能假设像/dev/ttyACM0
或或类似的设备也是如此/dev/ttyUSB0
.
docker run命令也适用于Linux主机.
Mar*_*lin 11
--device
直到您的USB设备拔出/重新插入,然后停止工作。您必须使用cgroup devices.allow解决它。
您可以使用-v /dev:/dev
它,但这是不安全的,因为它会将主机中的所有设备(包括原始磁盘设备等)映射到容器中。基本上,这允许容器在主机上获得root权限,这通常不是您想要的。
在这方面,使用cgroups方法更好,并且可以在容器启动后添加的设备上使用。
在此处查看详细信息:在不使用--privileged的情况下访问Docker中的USB设备
粘贴起来有点困难,但是简而言之,您需要获取字符设备的主要编号并将其发送给cgroup:
189是/ dev / ttyUSB *的主要号码,您可以通过'ls -l'获得。您的系统上的系统可能与我的系统上的系统不同:
root@server:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allow
(A contains the docker containerID)
Run Code Online (Sandbox Code Playgroud)
然后像这样启动您的容器:
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash debian:amd64
Run Code Online (Sandbox Code Playgroud)
否则,容器启动后任何新插入或重新启动的设备都将获得新的总线ID,并且将不允许在容器中访问它。
小智 11
如果您想动态访问可以在 docker 容器已经运行时插入的 USB 设备,例如访问刚刚连接到 /dev/video0 的 USB 网络摄像头,您可以在启动容器时添加 cgroup 规则。此选项不需要 --privileged 容器,只允许访问特定类型的硬件。
检查您要添加的设备类型的设备主要编号。您可以在linux 内核文档中查找它。或者您可以为您的设备检查它。例如,要检查连接到 /dev/video0 的网络摄像头的设备主编号,您可以执行ls -la /dev/video0
. 这会导致类似的结果:
crw-rw----+ 1 root video 81, 0 Jul 6 10:22 /dev/video0
Run Code Online (Sandbox Code Playgroud)
其中第一个数字 (81) 是设备主编号。一些常见的设备主号:
启动docker容器时添加规则:
--device-cgroup-rule='c major_number:* rmw'
为您要访问的每种类型的设备添加规则-v /run/udev:/run/udev:ro
-v /dev:/dev
因此,要将所有 USB 网络摄像头和 serial2usb 设备添加到您的 docker 容器,请执行以下操作:
docker run -it -v /dev:/dev --device-cgroup-rule='c 188:* rmw' --device-cgroup-rule='c 81:* rmw' ubuntu bash
Run Code Online (Sandbox Code Playgroud)
小智 8
只需一行一行地按照说明进行操作,所有步骤都有说明
想法是正确配置cgroup规则。首先,让我们找到您的 USB 设备的 cgroup 属性。运行以下命令:
$ ls -l /dev/ | grep ttyUSB
crw-rw-rw- 1 root dialout 188, 0 Mar 1 18:23 ttyUSB0 #Example output
Run Code Online (Sandbox Code Playgroud)
根据输出,您可以看到主要的 tty 设备组188
在我的情况下,因此我将继续进行。
您可以运行 docker image允许访问具有特定主编号的设备范围,docker 会在您的主机中为您添加所需的规则(这将在分离模式下运行 docker,我们稍后会附加到它):
docker run --device-cgroup-rule='c 188:* rmw' -itd --name my_container ubuntu
Run Code Online (Sandbox Code Playgroud)
现在的想法是添加一个脚本,每次插入或拔出 USB 设备时都会运行该脚本。关于自定义规则here和here关于传递参数的一些解释。在 ubuntu 上,您应该/etc/udev/rules.d/99-docker-tty.rules
以超级用户身份(sudo)创建文件:
ACTION=="add", SUBSYSTEM=="tty", RUN+="/usr/local/bin/docker_tty.sh 'added' '%E{DEVNAME}' '%M' '%m'"
ACTION=="remove", SUBSYSTEM=="tty", RUN+="/usr/local/bin/docker_tty.sh 'removed' '%E{DEVNAME}' '%M' '%m'"
Run Code Online (Sandbox Code Playgroud)
该文件为您的规则添加了新条目,基本上是说:每次插入add
或拔出tty 设备时,remove
运行提供的脚本并传递一些参数。如果您想更具体,您可以使用udevadm info --name=<device name>
查找其他参数,您可以根据这些参数过滤设备。您可以按照此处的建议测试规则。要应用这些规则:
root@~$ udevadm control --reload
Run Code Online (Sandbox Code Playgroud)
现在我们还需要以/usr/local/bin/docker_tty.sh
超级用户(sudo)的身份创建以下脚本。您可以看到它被设置为在我们之前创建的 udev 规则中运行。
#!/usr/bin/env bash
echo "Usb event: $1 $2 $3 $4" >> /tmp/docker_tty.log
if [ ! -z "$(docker ps -qf name=env_dev)" ]
then
if [ "$1" == "added" ]
then
docker exec -u 0 env_dev mknod $2 c $3 $4
docker exec -u 0 env_dev chmod -R 777 $2
echo "Adding $2 to docker" >> /tmp/docker_tty.log
else
docker exec -u 0 env_dev rm $2
echo "Removing $2 from docker" >> /tmp/docker_tty.log
fi
fi
Run Code Online (Sandbox Code Playgroud)
此脚本将在您正在运行的 docker 容器中创建 tty 设备,或者根据设备是否已插入或已拔出将其删除(类似于 Ubuntu 机器发生的情况 - 每次插入设备时,您都可以在/dev/
目录下看到它)。提示:检查/tmp/docker_tty.log
主机上的一些调试输出文件,此外,按照此处的建议调试 bash 脚本。
不要忘记使脚本可执行:
root@~$ chmod +x /usr/local/bin/docker_tty.sh
Run Code Online (Sandbox Code Playgroud)
现在连接到 docker,看看/dev/
当你插入和拔出设备时,设备是否出现在目录中:
docker exec -it my_container bash
Run Code Online (Sandbox Code Playgroud)
另一个选择是调整 udev,它控制设备的安装方式以及具有哪些权限。对于允许非 root 访问串行设备很有用。如果您有永久连接的设备,那么该--device
选项是最好的选择。如果您有临时设备,这是我一直在使用的:
默认情况下,会挂载串行设备,以便只有 root 用户才能访问该设备。我们需要添加 udev 规则以使非 root 用户可以读取它们。
\n\n创建名为 /etc/udev/rules.d/99-serial.rules 的文件。将以下行添加到该文件中:
\n\nKERNEL=="ttyUSB[0-9]*",MODE="0666"
MODE="0666" 将授予所有用户对 ttyUSB 设备的读/写(但不是执行)权限。这是最宽松的选项,您可能需要根据您的安全要求进一步限制此选项。您可以阅读 udev 以了解有关控制设备插入 Linux 网关时发生的情况的更多信息。
\n\n串行设备通常是短暂的(可以随时插入和拔出)。因此,我们可以\xe2\x80\x99t挂载在直接设备甚至/dev/serial文件夹中,因为当拔掉插头时这些可能会消失。即使您将它们重新插入并且设备再次显示,从技术上讲,它是与安装的文件不同的文件,因此 Docker 不会看到它。因此,我们将整个 /dev 文件夹从主机挂载到容器。您可以通过将以下卷命令添加到 Docker 运行命令来完成此操作:
\n\n-v /dev:/dev
如果您的设备是永久连接的,那么从安全角度来看,使用 --device 选项或更具体的卷安装可能是更好的选择。
\n\n如果您没有使用 --device 选项并安装在整个 /dev 文件夹中,您将需要以特权模式运行容器(我将检查上面提到的 cgroup 内容,看看这是否可以已删除)。您可以通过将以下内容添加到 Docker 运行命令来完成此操作:
\n\n--privileged
如果您的设备可以插入和拔出,Linux 不保证它将始终安装在同一个 ttyUSBxxx 位置(特别是如果您有多个设备)。幸运的是,Linux 会自动在 /dev/serial/by-id 文件夹中创建一个到设备的符号链接。该文件夹中的文件将始终以相同的名称命名。
\n\n这是简要概述,我有一篇博客文章介绍了更多详细信息。
\n 归档时间: |
|
查看次数: |
133129 次 |
最近记录: |