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


当前回答

另一种选择是调整udev,它控制设备的挂载方式和权限。用于允许非根用户访问串行设备。如果你有永久连接的设备,——device选项是最好的选择。如果你有短暂的设备,这是我一直在使用的:

1. 设置udev规则

默认情况下,串口设备被挂载,只有root用户可以访问该设备。我们需要添加一条udev规则,让非root用户也能读懂它们。

创建一个名为/etc/udev/rules.d/99-serial.rules的文件。在该文件中添加以下一行:

内核==“ttyUSB[0-9]*”,MODE=“0666”

MODE="0666"将给予所有用户对ttyUSB设备的读/写(但不执行)权限。这是最允许的选项,您可能希望根据您的安全需求进一步限制它。您可以阅读udev以了解更多关于控制设备插入Linux网关时发生的事情的信息。

2. 从主机到容器挂载在/dev文件夹中

Serial devices are often ephemeral (can be plugged and unplugged at any time). Because of this, we can’t mount in the direct device or even the /dev/serial folder, because those can disappear when things are unplugged. Even if you plug them back in and the device shows up again, it’s technically a different file than what was mounted in, so Docker won’t see it. For this reason, we mount the entire /dev folder from the host to the container. You can do this by adding the following volume command to your Docker run command:

- v / dev: / dev

如果您的设备是永久连接的,那么从安全角度来看,使用——device选项或更特定的卷挂载可能是更好的选择。

3.以特权模式运行container

如果你没有使用——device选项,并且挂载在整个/dev文件夹中,你将被要求运行容器的特权模式(我将检查上面提到的cgroup的东西,看看是否可以删除)。你可以通过在Docker run命令中添加以下命令来做到这一点:

——特权

4. 从/dev/serial/by-id文件夹访问设备

如果您的设备可以插拔,Linux并不保证它总是挂载在同一个ttyUSBxxx位置(特别是如果您有多个设备)。幸运的是,Linux会自动创建到/dev/serial/by-id文件夹中的设备的符号链接。此文件夹中的文件将始终命名相同。

这是一个快速的纲要,我有一篇博客文章详细介绍。

其他回答

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

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

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

还有一种更简单的共享usb设备的方法,没有——privileged标志。这样做:

Docker运行…——device=/dev/bus/usb——device=/dev/usb <container> .使用实例

另一种选择是调整udev,它控制设备的挂载方式和权限。用于允许非根用户访问串行设备。如果你有永久连接的设备,——device选项是最好的选择。如果你有短暂的设备,这是我一直在使用的:

1. 设置udev规则

默认情况下,串口设备被挂载,只有root用户可以访问该设备。我们需要添加一条udev规则,让非root用户也能读懂它们。

创建一个名为/etc/udev/rules.d/99-serial.rules的文件。在该文件中添加以下一行:

内核==“ttyUSB[0-9]*”,MODE=“0666”

MODE="0666"将给予所有用户对ttyUSB设备的读/写(但不执行)权限。这是最允许的选项,您可能希望根据您的安全需求进一步限制它。您可以阅读udev以了解更多关于控制设备插入Linux网关时发生的事情的信息。

2. 从主机到容器挂载在/dev文件夹中

Serial devices are often ephemeral (can be plugged and unplugged at any time). Because of this, we can’t mount in the direct device or even the /dev/serial folder, because those can disappear when things are unplugged. Even if you plug them back in and the device shows up again, it’s technically a different file than what was mounted in, so Docker won’t see it. For this reason, we mount the entire /dev folder from the host to the container. You can do this by adding the following volume command to your Docker run command:

- v / dev: / dev

如果您的设备是永久连接的,那么从安全角度来看,使用——device选项或更特定的卷挂载可能是更好的选择。

3.以特权模式运行container

如果你没有使用——device选项,并且挂载在整个/dev文件夹中,你将被要求运行容器的特权模式(我将检查上面提到的cgroup的东西,看看是否可以删除)。你可以通过在Docker run命令中添加以下命令来做到这一点:

——特权

4. 从/dev/serial/by-id文件夹访问设备

如果您的设备可以插拔,Linux并不保证它总是挂载在同一个ttyUSBxxx位置(特别是如果您有多个设备)。幸运的是,Linux会自动创建到/dev/serial/by-id文件夹中的设备的符号链接。此文件夹中的文件将始终命名相同。

这是一个快速的纲要,我有一篇博客文章详细介绍。

有几个选择。你可以使用——device标志,用户可以在没有——特权模式的情况下访问USB设备:

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

或者,假设您的USB设备在主机/dev/bus/usb上可用,并且驱动程序正在工作等,您可以使用特权模式和volumes选项将其挂载到容器中。例如:

docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu bash

注意,顾名思义,——privileged是不安全的,应该小心处理。

除了上面的答案,对于那些想要快速使用外部USB设备(HDD,闪存驱动器)在docker内部工作,而不使用特权模式的人:

在主机上找到你的设备的devpath:

sudo fdisk -l

您可以很容易地从列表中识别您的驱动器的容量。复制该路径(在下例中为/dev/sda2)。

Disque /dev/sda2 : 554,5 Go, 57151488 octets, 111624 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets

挂载这个devpath(最好是/media):

sudo mount <drive path> /media/<mount folder name>

然后你可以使用它作为docker运行的参数:

docker run -it -v /media/<mount folder name>:/media/<mount folder name>

或者在docker中合成volumes:

services:
  whatevermyserviceis:
    volumes:
      - /media/<mount folder name>:/media/<mount folder name>

现在,当您运行并进入容器时,您应该能够访问容器中的驱动器/media/<挂载文件夹名>

免责声明:

这可能不适用于串行设备,如网络摄像头等。 我只对USB存储驱动器进行了测试。 如果您需要定期重新连接和断开设备,这 方法将会很烦人,并且除非重置挂载路径并重新启动容器,否则将无法工作。 我使用docker 17.06 +在文档中规定