我希望能够从 Docker 容器内访问插入主机的 FTDI 串行到 USB 桥接设备。从那里,我使用带有 pyusb 和 libusb 库的 Python 脚本来处理 USB 输出。这样,我可以将 FTDI 板及其连接的设备插入某些计算机,运行 docker 容器并处理数据。该容器是使用 docker-compose 构建的。
我们是如何来到这里的
作为在我的主机上进行的早期测试,我编写了以下 Python 脚本,该脚本将在我的设计开始时运行:
import usb.core
import usb.util
# Find the USB device
device = usb.core.find(idVendor = 0x0403, idProduct = 0x601c)
# Check if the device was found. If not, raise an error. If the device was found, print out its info.
if (device == None):
raise ValueError('Device not found')
else:
print(device)
这会按预期打印出板上的所有信息 - 制造商、接口、端点等。 (我可以使用
lsusb -D /dev/bus/usb/003/007
找到供应商和产品 ID,其中数字是 lsusb
给出的总线和设备编号)。
然后我进入 vscode 中的 docker 容器,安装这两个库,并运行相同的脚本。这次,我遇到了错误:
usb.core.NoBackendError: No backend available
我访问了 pyusb 常见问题解答:https://github.com/pyusb/pyusb/blob/master/docs/faq.rst 并确保我没有找到导致错误的常见原因之一。即使我使用
usb.backend.libusb1.get_backend(...)
手动指定后端库,错误仍然存在。
我意识到问题的根本原因是 docker 容器首先无法访问 FTDI USB 设备。有了一周的 Docker 经验,我认为我需要使用以下命令将主机上的 USB 设备挂载到容器中:
已经尝试过什么
在 docker-compose 文件中的服务中,我尝试使用以下命令指定设备的安装位置:
devices:
- "/dev/serial/by-id/<link>:/dev/ttyUSB0"
privileged: true
为了找到 ,我进入了 /dev/serial/by-id/
目录并使用了
dmesg | grep tty
。每当我插入不同的 USB 设备 (Arduino) 时,它都会显示一个新条目,但当我插入 FTDI 板时,它不会显示任何新条目。因此,我怀疑我的 FTDI 板是 TTY 设备,大多数现有线程似乎都集中在该设备上。我不知道如何为 docker-compose 提供安装设备所需的内容。因为如果给定多个 USB 设备,pyusb 库就会找到我的设备,因此只需安装所有主机 USB 端口也应该可以解决我的问题。我也搜索了这组关键词,但没有找到太多有用的信息。
TL:博士
如何将主机上的单个 FTDI 串行到 USB 桥接设备或所有 USB 设备安装到 Docker 容器?如果可能的话,我想避免使用privileged
。我已经使用 Ubuntu、Docker 和 Python 工作了大约一周,所以我可能需要详细说明。如果需要更多信息,请告诉我。谢谢!
breakout)。我基本上只是按照 Adafruit here 上的说明进行操作。
我认为“无后端”错误是因为没有安装 libusb。不知道为什么,正如你所说,你安装了它......但这是我采取的步骤,据我认为它们是相关的:
RUN apk update && apk add libusb
。在完整的 Ubuntu 上,它将是
RUN apt update && apt install libusb-1.0
,如 Adafruit 指南中所示。
dev/serial/by-id
中的原因?在host 上,创建包含以下内容的文件
/etc/udev/rules.d/11-ftdi.rules
:
# /etc/udev/rules.d/11-ftdi.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6011", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6015", GROUP="plugdev", MODE="0666"
/dev/serial/by-usb
中获得一个新条目,我可以按照您的预期将其添加到撰写文件中。我的文件中的这些行是:
devices:
- "/dev/serial/by-id/usb-0403_6014-if00-port0:/dev/ftdi"
现在容器中的 pyusb 可以看到该设备(对我来说)。
编辑
当 pyusb 在容器中由 root 运行时,上述内容对我有用。我最近改用容器中的非管理员帐户,并且必须再执行两个步骤:
volumes:
- /etc/udev/rules.d/11-ftdi.rules:/etc/udev/rules.d/11-ftdi.rules:ro
RUN groupadd plugdev && usermod -a -G plugdev abc
您还可以查看上面链接的 Adafruit 指南的其余部分。它使用了更多的 Python 库(pyftdi 和 adafruit-blinka),这正是我用一行 Python 控制 GPIO 引脚所需要的。但你的用例可能比我的复杂得多!