Several customers contacted us because they were having difficulties executing the VirtualHub into a Docker container. Technically, you can do so, but we discourage the use of the VirtualHub in a Docker container. Here is why.
The interest of the VirtualHub is to offer a web interface to use and configure Yoctopuce modules connected on the USB ports of the machine. If the VirtualHub can't access the USB ports of the machine, the application has no interest anymore.
The issue with Docker is that it isolates the container from the physical machine. This has numerous advantages in the majority of applications, but not in our case because the container is also isolated from the USB devices.
Concretely, it's easy to run the VirtualHub into a Docker container, but the USB devices connected to the host are not listed inside the container.
If the Docker host is under Linux, you can work around this isolation but, as you are going to see, none of the solutions are truly satisfying.
Option 1: Not so good
The first possibility is to start the container with the --device option which enables the container to access the host devices. On paper, this is exactly what we want. When starting the container, we add the --device /dev/bus/usb option and the VirtualHub gets access to the USB ports:
docker container run --publish 4444:4444 --device /dev/bus/usb vhubContainer
But this solution has a large drawback: this option doesn't manage hot-plugging. You can use only the devices which are connected at the time when the container starts. If you add a Yoctopuce module later on, it isn't detected. Only the modules connected when the container starts are available. Worse, if you disconnect a detected module, it disappears forever.
The only solution to update the list of devices that the container sees is to restart it.
Option 2: Slightly better
The second option is to start the container in privileged mode and to use the --mount option to make the /dev/bus/usb directory available.
docker container run --publish 4444:4444 --privileged --mount type=bind,source=/dev/bus/usb,target=/dev/bus/usb vhubContainer
This option works slightly better as connections/disconnections of USB devices are propagated to the container. This being said, this solution is far from perfect because you must run the container in privileged mode, which breaks the concept of encapsulation and security.
Moreover, because of a limitation of the libUSB-1.0, the VirtualHub doesn't always automatically detect the new devices. For new USB devices to appear, you must restart the VirtualHub (only the executable, not the container), as the libUSB-1.0 then performs a complete enumeration and all the devices are correctly detected. It's better, but still not perfect.
Option 3: Still not ideal
The last option is to start the container with the options --device and --device-cgroup-rule.
docker container run --publish 4444:4444 --device /dev/bus/usb --device-cgroup-rule='c 189:* r
With this solution, you are in the same situation as with option 2, but without needing to run the container in privileged mode. However, this solution is more complex to use. You must run a Python script on the Docker host which searches for new USB devices and then adds the node in the container /dev/bus/usb subdirectory.
Note: This solution is inspired from the following example: https://github.com/th3mis/docker-usb-sync
Conclusion and solution
We didn't give many details for these three solutions because we think that none of them is a good solution. On top of the limitations that we just explained, there is a root issue.
The aim of a container is to separate a service from the host which runs it. But all the options that we mentioned only add a coupling between the container and the host.
The VirtualHub is intimately linked to the Yoctopuce USB modules. Adding a virtualization layer between the two brings nothing but problems.
The best solution is to execute the VirtualHub on the Docker host itself. After all, we connect a module on a USB port of the host, and not on a virtual USB port. The VirtualHub is available for all the OSes on which Docker runs and therefore you can use it under Linux, but also under Windows or macOS.
Finally, another solution is to connect the modules on a YoctoHub-Ethernet or a YoctoHub-Wireless-n which provide the same features as the VirtualHub.