I am a complete beginner at Docker, so please do easy on me.
I am trying to deploy a Django project in a Docker container on a Raspberry Pi 3B, but I am running into a problem accessing the GPIO ports.
Every time I try to initialise Docker with “sudo docker-compose up” I get the error: “RuntimeError: No access to /dev/mem. Try running as root!”
From what I have read, in order to get the Docker container to communicate with the GPIO ports the ‘user’ has to be a part of the ‘gpio’ group.
My questions are:
Docker File:
FROM python:3.8-alpine
ENV PATH="/scripts:${PATH}"
COPY ./requirements.txt /requirements.txt
RUN apk add --update --no-cache --virtual .tmp gcc libc-dev linux-headers
RUN pip install -r /requirements.txt
RUN pip install RPi.GPIO
RUN pip install apscheduler
RUN apk del .tmp
RUN mkdir /poolproject
COPY ./poolproject /poolproject
WORKDIR /poolproject
COPY ./scripts /scripts
RUN chmod +x /scripts/*
RUN mkdir -p /vol/web/media
RUN mkdir -p /vol/web/static
RUN adduser -D user
RUN chown -R user:user /vol
RUN chmod -R 755 /vol/web
USER user
CMD ["entrypoint.sh"]
docker-compose.yml
version: '3.7'
services:
app:
privileged: true
build:
context: .
ports:
- "8000:8000"
volumes:
- ./poolproject:/poolproject
command: sh -c "python manage.py runserver 0.0.0.0:8000"
environment:
- DEBUG=1
I apologize; I've retracted my earlier answer because I missed the fact that you already have privileged: true
in your docker-compose.yml
. You have a different problem.
First, the error from RPi.GPIO
is misleading: it doesn't really want access to /dev/mem
; it wants access to /dev/gpiomem
, which on the host has the following permissions:
pi@raspberrypi:~ $ ls -l /dev/gpiomem
crw-rw---- 1 root gpio 246, 0 Sep 7 09:02 /dev/gpiomem
Where the gpio
group has gid 997
:
pi@raspberrypi:~ $ getent group gpio
gpio:x:997:pi
That means we need to arrange for your web service to run with gid 997
inside your container. We can do that by adding the gpio
group inside your Dockerfile
, and then making your user
a member of that group:
RUN addgroup -g 997 gpio
RUN adduser -D -G gpio user
With this change, I'm able to run some my test code without errors. Additionally, it is no longer necessary to enable privileged
mode; we can replace privileged: true
in the docker-compose.yml
with a devices
entry to expose just the /dev/gpiomem
device.
This is everything I used to test the situation.
This is my Dockerfile
:
FROM python:3.8-alpine
RUN apk add --update --no-cache --virtual .tmp gcc libc-dev linux-headers
RUN pip install RPi.GPIO
RUN addgroup -g 997 gpio
RUN adduser -D -G gpio user
RUN mkdir -p /scripts
RUN chown -R user:gpio /scripts
COPY gpiotest.py /scripts/gpiotest.py
RUN chmod 755 /scripts/gpiotest.py
CMD python /scripts/gpiotest.py
USER user
This is my docker-compose.yml
:
version: '3.7'
services:
app:
build:
context: .
devices:
- /dev/gpiomem:/dev/gpiomem
This is my gpiotest.py
script:
#!/usr/bin/python
import sys
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
while True:
val = GPIO.input(17)
print('value:', val)
sys.stdout.flush()
time.sleep(1)