Permission denied when accessing ttyUSB in a privileged docker container using "docker exec"

Viewed 1578

I'm trying to access the serial port (as a user) in my privileged docker container which is already running, but I'm getting "permission denied" errors, while the permissions should be correctly set. As a minimal reproducible example (assuming serial device is connected to /dev/ttyUSB0):

# start docker container with your user id, give it privileged access and mount /dev
docker run -itd --user $(id -u) --name test --privileged -v /dev:/dev ubuntu
# add user and add it to dialout (not sure if this is necessary as we have privileged access)
docker exec -it --user 0 test sh -c "groupadd -g $(id -g) user && useradd -m -u $(id -u) -g $(id -g) -G dialout user"
# install picocom to test serial connection
docker exec -it --user 0 test sh -c "apt update && apt install -y picocom"
# run picocom on /dev/ttyUSB0 to check if we can open it
docker exec -it test sh -c "picocom /dev/ttyUSB0"

But when trying this I get this error:

FATAL: cannot open /dev/ttyUSB0: Permission denied

It's working fine when I execute the command as root, or when I access the serial device directly in the "docker run" command, but I need to be able to access the serial device from an already running container.

Does anyone know what I'm missing?

3 Answers

Thanks to @sawdust for pointing me to the answer.

The problem was that I'm running an ubuntu docker container in Manjaro (Arch) OS, and on Arch ttyUSB is owned by uucp (group id 987), while on ubuntu it's owned by dialout (group id 20).

So when mounting /dev/ttyUSB0 into the docker container, it's still owned by gid 987, but in the ubuntu environment this group id is not dialout, so even when adding the user to dialout, the user has no permission to open the serial port.

A quickfix would be to create a group with the correct gid and add your user to it:

docker exec -it --user 0 test sh -c "groupadd -g 987 ttyusb && usermod -a -G ttyusb user"

but it's not a complete solution, as this will only make it work for your combination of host OS and docker OS, and not necessarily for other user with different environments.

If it is still relevant, the following solution did work for me:

docker run --gpus all -it --privileged --name [container_name] \
        -v "$(pwd)/..":/home/app \
        -v /dev/bus/usb:/dev/bus/usb \
        -v /dev/ttyACM0:/dev/ttyACM0 \
        [image_container_name] bash

Note that you might not need in your application the "gpu" so you can remove that flag "--gpus all"

using "docker run --rm --group-add 986 -it --privileged ... " resolves.

if you call groups, show error but works.

$ groups

dcuser dialout staff groups: cannot find name for group ID 986

986

Related