web-dev-qa-db-fra.com

Partage de périphériques (webcam, clés USB, etc.) avec Docker

J'ai besoin de partager des périphériques spécifiques à partir de /dev sur ma machine hôte Linux avec mes conteneurs Docker.

L'indicateur --privileged permet de partager les périphériques présents dans /dev présents au moment où docker run est appelé, mais les périphériques ajoutés ou supprimés par la suite ne se propagent pas dans le conteneur.

J'ai essayé docker run -v=/dev:/dev ..., mais cela a abouti à visser avec les permissions et la propriété de fichiers comme/dev/pts, ce qui a empêché la machine hôte de créer de nouveaux terminaux psuedo.

J'ai également essayé l'indicateur --device, mais cela ne vous permet pas de partager un périphérique qui n'existe pas encore.

Enfin, j'ai essayé de partager des volumes pour des périphériques tels que -v=/dev/video0:/dev/video0, mais si/dev/video0 n'existait pas avant l'exécution, docker crée un répertoire et une webcam ne prendra pas/dev/video0 lorsqu'il est branché.

Existe-t-il un meilleur moyen d’obtenir cette fonctionnalité prise en charge?

23
Ryan

Vous cherchez vérifier le drapeau --device

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

Bonne journée!

14
Auzias

Je pense qu'en théorie, il est possible d'utiliser le drapeau --privileged, car cela vous donne la possibilité d'accéder à tous les périphériques hôtes. Si vous installez usbutils ou similaire (selon la distribution de vos images), vous verrez que le conteneur privilégié peut voir les périphériques branchés à chaud lors de l'exécution de lsusb. Malheureusement, ils ne s'affichent pas sous/dev. Écrire par script la création de ces descripteurs et les faire gérer correctement par votre logiciel sous/dev peut devenir assez compliqué malheureusement. Cela ne doit pas nécessairement être ainsi pour vos appareils.

Ce que vous pouvez faire en premier lieu, c’est de les créer à l’aide de mknod . J’ai essayé ceci avec mon téléphone HTC et cela a fonctionné (détails non pertinents ici), il suffit de vérifier la ligne du périphérique branché à chaud dans lsusb:

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

allez dans le bon dossier pour le descripteur:

cd /dev/bus/usb/003

vérifiez la version principale du pilote USB dans votre noyau à partir des descripteurs existants:

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 :) => créez le signe de tête et utilisez pour ce faire la version mineure 0.

mknod 002 c 189 0

=> au moins lsusb -v est maintenant capable d'ouvrir le périphérique. Même chose devrait fonctionner pour la plupart des matériels imo, à quelques exceptions près.

Ce que vous pouvez faire comme alternative, quoique peut-être plus lentement, mais certainement plus sûr et plus dans l’esprit de Docker et de la conteneurisation, consiste à utiliser des conteneurs pour accéder à vos périphériques lorsque vous les montez à chaud, puis que vous les partagez avec le conteneur principal exécutant votre application vidéo. via socat tty via tcp.

Disons que vous branchez/dev/video0 sur l'hôte, vous pouvez créer un nouveau conteneur dans lequel ce périphérique est monté. Ce conteneur (sur lequel socat est installé) pourrait exécuter:

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

En supposant que cette chose a le nom d’hôte video0-server, vous pouvez maintenant créer le descripteur pour video0 sur le client via:

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

Maintenant, vous devriez pouvoir utiliser l'appareil correctement. Je pense que pour de nombreux appareils, les frais généraux de socat ne devraient pas être un problème. Si la création de scripts via plusieurs conteneurs qui communiquent dynamiquement avec votre conteneur principal via la mise en réseau est une option et que les performances ne sont pas affectées de manière significative par la surcharge, cette dernière option est plus propre et plus sûre que le mode --privileged à mon avis.

10
Armin Braun

Il est difficile de placer le périphérique lorsque le système est en cours d'exécution (détection USB). Vous devez créer un script pour placer les périphériques tels qu'ils ont été trouvés et effectuer le --rm (de sorte que chaque fois que vous quittez la machine, elle est supprimée et que nouvelle chance d'importer les appareils)

0