31

I have a need to share specific devices from /dev on my host Linux machine with my docker containers.

The --privileged flag works for sharing any devices in /dev that are present at the time docker run is called, but any subsequently added or removed devices do not propagate into the container.

I tried docker run -v=/dev:/dev ... but that ended up screwing with the permissions and ownership of files like /dev/pts, leading to the host machine to not be able to create new psuedo-terminals.

I also tried the --device flag, but that doesn't allow you to share a device that doesn't yet exist.

Finally, I tried sharing volumes for devices like -v=/dev/video0:/dev/video0 but if /dev/video0 doesn't exist before run, docker creates a directory there and a webcam will not take /dev/video0 when plugged in.

Is there any better way to get this supported functionality?

Ryan
  • 3,595
  • 3
  • 26
  • 31

3 Answers3

22

You are looking check the flag --device

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

Have a nice day!

Auzias
  • 3,064
  • 11
  • 34
  • 4
    The problem with the --device flag is that it fails if the device isn't already present. I have a pretty complicated setup where 4 USB webcams and 4 SD cards are regularly plugged/unplugged from a server, and a few Docker apps are connecting to the webcams and saving data to the cards. – Ryan Dec 16 '15 at 15:31
  • Oh, I see. That's indeed pretty complicated and I'm unsure that Docker has cleared out this kind of situations yet. The only advice I can give you would be to simplifies it if ever it is possible, but it may not fit with your other constraints. – Auzias Dec 17 '15 at 07:33
15

I think in theory this is possible for sure using the --privileged flag, as this thing gives you the ability to access all the hosts devices. If you install usbutils or similar ( depending on your images Distribution ) you'll see that the privileged container is able to see hotplugged devices when running lsusb. Unfortunately though they do not show up under /dev. Scripting the creation of those descriptors and have them properly handled by your software under /dev can become fairly involved unfortunately. It doesn't have to be that way for your devices though.

What you can do as a first attempt is to just create them using mknod. I tried this out with my HTC phone and it sort of worked ( details not relevant here ), simply check the line for the hotplugged device in lsusb:

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

go to the correct folder for the descriptor:

cd /dev/bus/usb/003

check the major version for the usb driver in your kernel from the existing descriptors:

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 :) => create the nod and while doing so use minor version 0.

mknod 002 c 189 0

=> at least lsusb -v is now capable of opening the device. Same should work out for most hardware imo, with some exceptions.

What you could do as an alternative, though possibly slower but certainly safer and more in the spirit of Docker and containerization is to use containers for accessing your devices when you hot-mount them and then share the devices with the main container running your video app via socat tty via tcp.

Say you hotplug /dev/video0 on the host, you could spin up a new container that has this device mounted in that event. This container ( that has socat installed ) could run:

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

Assuming this thing has the hostname video0-server you could now create the descriptor for video0 on the client via:

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

Now you should be able to use the device just fine. For many devices the socat overhead should not be an issue I think. If scripting this via multiple containers that dynamically communicate with your main container via networking is an option and the performance is not affected in any meaningful way by the overhead too, the latter option is cleaner and safer than --privileged mode in my opinion.

Armin Braun
  • 3,379
  • 1
  • 14
  • 33
  • Why not just use the `--device` flag instead? – Auzias Jun 14 '16 at 06:15
  • 5
    @Auzias because the person asked for a solution that would allow plugging devices into an already running container. `--device` will not help you in this scenario :) – Armin Braun Jun 14 '16 at 17:33
0

It is difficult to place the device when the system is running (USB detection) you should make an script to place the devices as they are found and do the --rm (so each time you exit the machine is removed, and you have a new chance to import the devices)