I'm trying to use gpiozero
to control GPIO in a container on Raspberry Pi 5.
My simple LED blink application is
from gpiozero import LED
from time import sleep
led = LED(17)
while True:
led.on()
sleep(1)
led.off()
sleep(1)
While it works fine on the host, I can't get it to work from a Docker container. When I create the container with:
docker run --privileged --device /dev/gpiochip4 -v /dev:/dev -v /sys:/sys blinker:latest
I get the error Unable to load any default pin factory!
.
Here is the whole error trace:
/usr/local/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from lgpio: module 'lgpio' has no attribute 'SET_BIAS_DISABLE'
warnings.warn(
/usr/local/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from rpigpio: No module named 'RPi'
warnings.warn(
/usr/local/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from pigpio: failed to connect to localhost:8888
warnings.warn(
/usr/local/lib/python3.11/site-packages/gpiozero/devices.py:300: PinFactoryFallback: Falling back from native: unable to determine gpio base
warnings.warn(
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Can't connect to pigpio at localhost(8888)
Did you start the pigpio daemon? E.g. sudo pigpiod
Did you specify the correct Pi host/port in the environment
variables PIGPIO_ADDR/PIGPIO_PORT?
E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888
Did you specify the correct Pi host/port in the
pigpio.pi() function? E.g. pigpio.pi('soft', 8888)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Traceback (most recent call last):
File "//blink.py", line 5, in <module>
led = LED(17)
^^^^^^^
File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 108, in __call__
self = super().__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/gpiozero/output_devices.py", line 192, in __init__
super().__init__(pin, active_high=active_high,
File "/usr/local/lib/python3.11/site-packages/gpiozero/output_devices.py", line 74, in __init__
super().__init__(pin, pin_factory=pin_factory)
File "/usr/local/lib/python3.11/site-packages/gpiozero/mixins.py", line 75, in __init__
super().__init__(*args, **kwargs)
File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 544, in __init__
super().__init__(pin_factory=pin_factory)
File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 245, in __init__
Device.ensure_pin_factory()
File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 270, in ensure_pin_factory
Device.pin_factory = Device._default_pin_factory()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/gpiozero/devices.py", line 302, in _default_pin_factory
raise BadPinFactory('Unable to load any default pin factory!')
gpiozero.exc.BadPinFactory: Unable to load any default pin factory!
To create the image I used the following Dockerfile:
FROM python:3.11
COPY blink.py ./
RUN pip install lgpio pigpio gpio gpiozero
CMD ["python", "blink.py"]
In addition, I tried to expose port 8888, and I tried to expose differnt volumes under /dev
folder. I validated daemon was running using sudo pigpiod
and sudo systemctl enable pigpiod
.
I found a workaround on GitHub in the repository PY_LGPI. You can update your Dockerfile as follows:
FROM python:3.11
COPY blink.py ./
RUN pip install lgpio pigpio gpio gpiozero
RUN wget https://github.com/Gadgetoid/PY_LGPIO/releases/download/0.2.2.0/lgpio-0.2.2.0.tar.gz
RUN pip install lgpio-0.2.2.0.tar.gz
CMD ["python", "blink.py"]
Then, you can run the Docker container with the following command:
docker run --privileged blinker:latest
This should resolve the issue you were facing.