【问题标题】:Sharing devices (webcam, USB drives, etc) with Docker与 Docker 共享设备(网络摄像头、USB 驱动器等)
【发布时间】:2018-03-10 02:52:23
【问题描述】:

我需要在我的主机 Linux 机器上与我的 docker 容器共享来自 /dev 的特定设备。

--privileged 标志用于共享 /dev 中在调用 docker run 时存在的任何设备,但任何随后添加或删除的设备都不会传播到容器中。

我尝试了docker run -v=/dev:/dev ...,但最终搞砸了 /dev/pts 等文件的权限和所有权,导致主机无法创建新的伪终端。

我也尝试了--device 标志,但这不允许您共享尚不存在的设备。

最后,我尝试为-v=/dev/video0:/dev/video0 之类的设备共享卷,但如果 /dev/video0 在运行前不存在,docker 会在那里创建一个目录,并且网络摄像头在插入时不会占用 /dev/video0。

有没有更好的方法来获得这个支持的功能?

【问题讨论】:

    标签: linux docker device


    【解决方案1】:

    你正在寻找检查标志--device

       --device=[]
          Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)
    

    祝你有美好的一天!

    【讨论】:

    • --device 标志的问题是,如果设备不存在,它会失败。我有一个非常复杂的设置,其中 4 个 USB 网络摄像头和 4 个 SD 卡定期从服务器插入/拔出,并且一些 Docker 应用程序连接到网络摄像头并将数据保存到卡中。
    • 哦,我明白了。这确实很复杂,我不确定 Docker 是否已经清除了这种情况。我能给你的唯一建议是尽可能简化它,但它可能不适合你的其他限制。
    【解决方案2】:

    我认为理论上这肯定可以使用--privileged 标志,因为这个东西使您能够访问所有主机设备。如果您安装 usbutils 或类似的(取决于您的图像分发),您将看到特权容器在运行 lsusb 时能够看到热插拔设备。 不幸的是,尽管它们没有出现在 /dev 下。不幸的是,编写这些描述符的创建脚本并让您的软件在 /dev 下正确处理它们可能会变得相当复杂。不过,您的设备不一定要这样。

    您可以做的第一次尝试是使用 mknod 创建它们。 我用我的 HTC 手机试了一下,它有点工作(细节在这里不相关),只需检查 lsusb 中热插拔设备的线路:

    Bus 003 Device 002: ID 0bb4:0f25 HTC (High Tech Computer Corp.) One M8
    

    转到描述符的正确文件夹:

    cd /dev/bus/usb/003
    

    从现有描述符中检查内核中 USB 驱动程序的主要版本:

    root@1a11f7c329a9:/dev/bus/usb/003# ls -la
    total 0
    drwxr-xr-x 2 root root      160 Dec 26 13:40 .
    drwxr-xr-x 6 root root      120 Dec 26 13:30 ..
    crw-rw-r-- 1 root root 189, 256 Dec 26 13:30 001
    crw-rw-r-- 1 root root 189, 258 Dec 26 13:30 003
    crw-rw-r-- 1 root root 189, 259 Dec 26 13:30 004
    crw-rw-r-- 1 root root 189, 260 Dec 26 13:30 005
    crw-rw-r-- 1 root root 189, 261 Dec 26 13:30 006
    

    => 189 :) => 创建点头,同时使用次要版本 0。

    mknod 002 c 189 0
    

    => 至少lsusb -v 现在能够打开设备。对于大多数硬件 imo 来说,应该也是如此,但有一些例外。

    您可以做的替代方法是,在热挂载设备时使用容器来访问您的设备,然后与运行的主容器共享设备,虽然可能会更慢但肯定更安全,而且更符合 Docker 和容器化的精神您的视频应用通过 socat tty 通过 tcp。

    假设您在主机上热插拔 /dev/video0,您可以启动一个新容器,该容器在该事件中安装了该设备。此容器(已安装 socat)可以运行:

    socat tcp-l:54321,reuseaddr,fork file:/dev/video0,nonblock,waitlock=/var/run/video0.lock
    

    假设这个东西的主机名是 video0-server,你现在可以通过以下方式在客户端上为 video0 创建描述符:

    socat pty,link=/dev/video0,waitslave tcp:video0-server:54321
    

    现在您应该可以正常使用该设备了。对于许多设备,我认为 socat 开销应该不是问题。 如果通过多个通过网络与主容器动态通信的容器编写脚本是一个选项,并且开销也不会以任何有意义的方式影响性能,那么在我看来,后一个选项比--privileged 模式更干净、更安全。

    【讨论】:

    • 为什么不直接使用--device 标志呢?
    • @Auzias 因为该人要求提供一种允许将设备插入已经运行的容器的解决方案。 --device 在这种情况下不会帮助你:)
    【解决方案3】:

    在系统运行时很难放置设备(USB检测),您应该编写一个脚本来放置找到的设备并执行--rm(因此每次退出机器时都会删除,并且你有一个新的机会来导入设备)

    【讨论】:

      猜你喜欢
      • 2010-10-20
      • 2015-01-07
      • 2013-03-14
      • 2011-07-02
      • 2016-02-03
      • 2012-04-24
      • 2012-08-16
      • 1970-01-01
      • 2019-09-28
      相关资源
      最近更新 更多