Getting GPIO to work in container

Question

I am trying to access the GPIO pins using the Python module gpiozero, from within a container.

gpiozero can work with several low level libraries - or pin factories.
I tried several, and the all give problems related to permissions.

Maybe this has to to with running from inside a container?
Who can help?

I am using a raspberry pi zero.

Setup to reproduce error

Let me show you what happens if I use the RPI-Gpio library as backbend. The same library is used in the example repo balena-rpi-gpio-sample-with-python .

Dockerfile.template looks like this:

FROM balenalib/%%BALENA_MACHINE_NAME%%-python:3.11.2-run
RUN apt update -y; apt upgrade -y
RUN apt -y install build-essential
RUN pip install rpi-gpio==0.7.1 gpiozero==1.6.2
ENV GPIOZERO_PIN_FACTORY=rpigpio

docker-compose.yml

version: "2"

services:
  irrigation:
    build: .
    ports:
      - "80:8000"

Then in the docker container I execute the following python script (I use the interactive interpreter)

from gpiozero import OutputDevice
v = OutputDevice(23)

Error

It gives the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 108, in __call__
    self = super(GPIOMeta, cls).__call__(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/gpiozero/output_devices.py", line 83, in __init__
    super(OutputDevice, self).__init__(pin, pin_factory=pin_factory)
  File "/usr/local/lib/python3.11/site-packages/gpiozero/mixins.py", line 85, in __init__
    super(SourceMixin, self).__init__(*args, **kwargs)
  File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 549, in __init__
    pin = self.pin_factory.pin(pin)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/gpiozero/pins/pi.py", line 103, in pin
    pin = self.pin_class(self, n)
          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/gpiozero/pins/rpigpio.py", line 111, in __init__
    GPIO.setup(self.number, GPIO.IN, self.GPIO_PULL_UPS[self._pull])
RuntimeError: No access to /dev/mem.  Try running as root!

Within the container I am root:

>>> root@3833176168f5:/# whoami
root

Follow Python gpio example to produce same error

Follwoing the script in the Python gpio example closely, I get the same error

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setmode(GPIO.BOARD)
GPIO.output(23, 1)
RuntimeError: No access to /dev/mem.  Try running as root!

Privilaged container needed

The solution was to update docker-compose.yml and make the container privileged:

services:
    irrigation:
        privileged: true

Hello,

I’ve only just seen this - but nice one on finding out the solution by yourself :slight_smile:
One other option that is worth noting for anyone that comes across this in the future, is that you could use the labels here: docker-compose.yml fields - Balena Documentation , specifically io.balena.features.sysfs I believe, to bind mount the host /sys in your container and thus make it accessible, without having to enable privileged mode. But if having a privilaged container is not a concern, then that solution works just as well

Thanks rcooke-warwick

Indeed I want to avoid privileged mode.

Perhaps it is a good idea to add this caveat for multi container projects to your tutorials / example on GPIO that run in a single container. That would make it easier for beginners.