Docker et le VirtualHub

Docker et le VirtualHub

Nous avons plusieurs clients qui nous ont contactés, car ils ont des difficultés à exécuter le VirtualHub dans un conteneur Docker. C'est techniquement possible, mais on décourage l'utilisation du VirtualHub dans un conteneur Docker. Voilà pourquoi.





L'intérêt du VirtualHub est de proposer une interface Web pour utiliser et configurer les modules Yoctopuce branchés sur les ports USB de la machine. Si le VirtualHub ne peut pas accéder aux ports USB de la machine, l'application n'a plus aucun intérêt.

Le problème avec Docker est qu'il isole le conteneur de la machine physique. Cela a de nombreux avantages pour la majorité des applications, mais pas dans notre cas car le conteneur est aussi isolé des périphériques USB.

Concrètement, il est facile d'exécuter le VirtualHub dans un conteneur Docker, mais les périphériques USB branchés sur l'hôte ne sont pas listés à l'intérieur du conteneur.

Si l'hôte Docker est sous Linux, il est possible de contourner cette isolation mais, comme vous allez le voir, aucune de ces options n’est vraiment satisfaisante.

Option 1: Bof bof


La première possibilité est de démarrer le conteneur avec l'option --device qui permet au conteneur d'accéder à un périphérique de l'hôte. Sur le papier, c'est exactement ce que l'on veut. Lors du démarrage du conteneur, on ajoute l'option --device /dev/bus/usb et le VirtualHub peut accéder aux ports USB:

docker container run --publish 4444:4444 --device /dev/bus/usb vhubContainer



Mais cette solution présente un gros inconvénient: Cette option ne gère pas le hot-plug. Seuls les appareils connectés au démarrage du conteneur sont utilisables. Si vous ajoutez un module Yoctopuce par la suite, il ne sera pas détecté. Seuls les modules connectés au moment du démarrage du conteneur sont utilisables. Pire, si on débranche un module détecté, il disparaît à jamais.

La seule solution pour mettre à jour la liste des périphériques vus par le conteneur est de le redémarrer.

Option 2: un peu mieux


La deuxième option est de démarrer le conteneur en mode privileged et d'utiliser l'option --mount pour rendre accessible le répertoire /dev/bus/usb.

docker container run --publish 4444:4444 --privileged --mount type=bind,source=/dev/bus/usb,target=/dev/bus/usb vhubContainer



Cette option fonctionne un peu mieux puisque les connexions/déconnexions des périphériques USB sont propagées vers le conteneur. Cela dit,
cette solution est loin d'être parfaite, car il faut exécuter le conteneur en mode privilégié, ce qui casse concept d'encapsulation et de sécurité.

Deuxièmement, en raison d'une limitation de la libUSB-1.0, le VirtualHub ne détecte toujours pas automatiquement les nouveaux appareils. Pour que les nouveaux périphériques USB apparaissent, il faut redémarrer le VirtualHub (uniquement l'exécutable, pas le conteneur), la libUSB-1.0 fera une énumération complète et tous les périphériques seront correctement détectés. C'est mieux, mais toujours pas parfait.

Option 3: toujours pas idéale


La dernière option est de démarrer le conteneur avec les options --device et --device-cgroup-rule.

docker container run --publish 4444:4444 --device /dev/bus/usb --device-cgroup-rule='c 189:* rmw' vhubContainer



Avec cette solution, vous êtes dans la même situation que l'option 2, mais sans avoir besoin d'exécuter le conteneur en mode privileged. Cependant, cette solution est plus compliquée utiliser. Vous devez exécuter un script Python sur l'hôte Docker qui recherche de nouveaux périphériques USB puis ajoute le nœud dans le sous-répertoire /dev/bus/usb du conteneur.

Note: Cette solution est inspirée de l'exemple suivant: https://github.com/th3mis/docker-usb-sync

Conclusion et solution


Nous n'avons pas trop détaillé ces trois options, car nous pensons qu'aucune n'est une bonne solution. En plus des limitations que nous venons de vous expliquer, il y a un problème de fond.

Le but d'un conteneur est de découpler un service de l'hôte qui l'exécute. Or, toutes les options que nous venons de mentionner ne font qu'ajouter un couplage entre le conteneur et l'hôte.

Le VirtualHub est intiment lié aux modules Yoctopuce USB. Ajouter une couche de virtualisation entre les deux n'apporte rien sauf des problèmes.

La meilleure solution est d'exécuter le VirtualHub sur l'hôte Docker lui-même. Après tout, on branche un module sur un port USB de l'hôte et non sur un port USB Virtuel. Le VirtualHub est disponible sur tous les OS sur lesquels fonctionne Docker et donc est utilisable sous Linux, mais aussi sous Windows ou macOS.

Enfin, une autre solution est de brancher les modules sur un YoctoHub-Ethernet ou YoctoHub-Wireless-n qui offre les mêmes fonctionnalités que le VirtualHub.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.