2018/12/20
Accessing USB Devices In Docker (ttyUSB0, /dev/bus/usb/... for fastboot, adb) without using --privileged
π
2018-12-20 01:01
in Linux
Problem:You want to use devices like /dev/ttyUSB0 or need to access raw USB devices under /dev/bus/usb in a docker container
This is not going to work easily for a variety of reasons. Let's go through them. Before I go there, yes, giving --privileged will "fix" all your problems but it will also give full access to everything in your container, where the container can wipe the host device, steal password from memory outside the container and so forth. Maybe that's ok for you anyway, but if not, read on:/dev/ttyUSB0 does not show up under /dev in the container
This does 2 things: 1) create the device in the container, and 2) give the container write access to the block device (more or that later)docker run --device=/dev/ttyUSB0 -i -t --entrypoint /bin/bash --cap-add SYS_PTRACE debian:amd64I added SYS_PTRACE so that you can use
strace -e trace=file command
to debug access problems
/dev/bus or /dev/serial do not show up under /dev in the container
Try this:docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash --cap-add SYS_PTRACE debian:amd64This will make /dev/bus and /dev/serial show up as bind mounts in your container. Yet you will find that _fastboot devices or adb_ will not work. Strace will show you permission denied. What you want instead is this:
docker run --device=/dev/bus -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash --cap-add SYS_PTRACE debian:amd64See https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities This mounts /dev/bus in your container and gives you access to all the block/character devices in there. Now, fastboot will work. Well, it will work until...
/dev/bus, fastboot/adb work until I disconnect/reconnect the device
Yeah, this is where things get more hairy. what the --device command above did was give access to all the block/character devices that existed when your container was created. If new ones appear (unplugging and replugging a device or rebooting it), those don't work.I have not found a way to get docker to make them work after the container has started. Thankfully there is a clue here: https://www.kernel.org/doc/Documentation/cgroup-v1/devices.txt You want to go back to running
docker run -v /dev/bus:/dev/bus:ro -v /dev/serial:/dev/serial:ro -i -t --entrypoint /bin/bash --cap-add SYS_PTRACE debian:amd64Then, grab the container ID in $A:
A=$( docker ps |awk '/bin.bash/ { print $1 }' )Note the major number of your device:
root@fuchsia-tests-x64-lab01-0002:/sys/fs/cgroup# l /dev/bus/usb/004/* | head -1 crw-rw-r-- 1 root root 189, 384 Dec 18 17:51 /dev/bus/usb/004/001Here it's 189. What changes it the minor number (384) when you plug/unplug devices. Finally, tell the linux container via an opaque cgroup interface, that all character devices of major number 189, are allowed:
root@fuchsia-tests-x64-lab01-0002:~# echo 'c 189:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allowAfter that, things should work.
My /dev/ttyUSB device keeps changing and the new one isn't allowed
See above and runroot@fuchsia-tests-x64-lab01-0002:~# echo 'c 188:* rwm' > /sys/fs/cgroup/devices/docker/$A*/devices.allowThen inside the container, create them all:
root@f47dbbab392b:/dev# for i in $(seq 1 255); do mknod ttyUSB$i c 188 $i; doneHope this helps!