Docker with device [GPIO] access while running as a specified user that is not `root`

We have an internal test system for our multi-platform software library which runs, with its zoo of third-party tools, inside an [Ubuntu] Docker container.

To keep things simple, the host machine AND the Docker container both run as the same user, test_user, fixed as UID 1000/GID 1000; this way volumes can be mapped between the two without issue.

However, I now need the Docker container to be able to access devices on the host machine (e.g. GPIOs). This ONLY seems to work if I run the Docker container specifically as the root user, i.e. this successfully permits access to GPIOs on the host (as evidenced by gpiodetect, which uses the libgpio API that we now want to test):

docker run -t --rm -i -u root --privileged -v /sys:/sys -v /dev:/dev docker_image /bin/bash
root@f1f7ca240c1e:/workdir# gpiodetect
gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)

…whereas, if I add test_user to the root group, both inside the Docker container and on the host machine, none of these do:

docker run -t --rm -i -u test_user --privileged -v /sys:/sys -v /dev:/dev docker_image /bin/bash
test_user@57130c86c196:/workdir$ gpiodetect
gpiodetect: unable to access GPIO chips: Permission denied
docker run -t --rm -i -u 1000:1000 --privileged -v /sys:/sys -v /dev:/dev docker_image /bin/bash`
test_user@57130c86c196:/workdir$ gpiodetect
gpiodetect: unable to access GPIO chips: Permission denied

Unfortunately running the Docker container as root, as well as not being desirable, is not an easy option as it messes up the mappings with the host machine (lots of shouts of dubious users from Git and the like).

Is there a way to persuade Docker that the [non-root] user it is running as has root privileges and so can have GPIO access?

FYI, on the host:

host:~ $ groups test_user
test_user: test_user root

…and in the Docker container:

test_user@1716f343e8c7:/workdir$ groups test_user
test_user: test_user root
test_user@1716f343e8c7:/workdir$
Asked By: Rob

||

Rather than persuading Docker of anything, just give test_user access to the gpiochips on both the host and docker_image. Then you can run Docker as test_user as before.

Typically on the Pi, the gpios are in the gpio group, so add test_user to that group (adduser test_user gpio), in both the host and the docker_image.

Not sure if that is valid for Ubuntu on Pi though (being a Raspberry Pi OS user myself). If not you will need to setup a group on the gpiochips as well. But as long as test_user has the appropriate permissions to access the gpiochip devices, in both the host and docker image, you should be good.

e.g. this works for me with no root involvement:

pi@devpi4:~ $ docker run -t --rm -i -u test_user --privileged -v /sys:/sys -v /dev:/dev libgpiod_axs gpiodetect
gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)

where the libgpiod_axs image is an image with libgpiod installed, and has a test_user who is a member of the gpio group, as is the pi user on the host (who could equally be named test_user). Note that the GID of the group must match in the docker image and host.

Answered By: Kent Gibson

@kent-gibson’s answer above is the business. To be explicit, I added to our Dockerfile:

RUN groupadd -g 997 gpio &&                                                                   
    echo SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660" >> /etc/udev/rules.d/99-com.rules

…(997 being the ID of the gpio group in the underlying Raspbian OS, I wonder if I even needed the udev rule, just the group IDs to match…?) and then at the end of Dockerfile, where test_user is created I added it to the gpio group and job’s a good ‘un, the test_user has access to the GPIOs from within the Docker image.

Also, as Kent points out, I removed the /sys mapping into the Docker container as it was entirely unnecessary.

Answered By: Rob
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.