How to Access Raspberry Pi GPIO Pins Inside a Docker Container

Disclosure: This post may contain affiliate links. If you make a purchase through these links, I may earn a small commission at no additional cost to you. If you are building a homelab or automating your home network, you'll eventually want to run lightweight services on a Raspberry Pi 4 using Docker. Docker is fantastic for keeping your dependencies isolated, but that isolation becomes a hurdle when your containerized app needs to interact with physical hardware—like the Pi's GPIO (General Purpose Input/Output) pins.
By default, Docker containers do not have access to the host machine's hardware. If you try to run a script inside a container that toggles a GPIO pin, it will likely crash with a "permission denied" or "device not found" error.
Here is how to fix it properly without compromising your system's security.
The Solution: Mapping /dev/gpiomem
Many tutorials online will tell you to run your Docker container in --privileged mode to solve hardware access issues. Avoid doing this if possible. Privileged mode strips away almost all of Docker's security isolation, giving the container root-level access to your entire host system.
Instead, the secure and elegant solution is to explicitly pass only the GPIO memory interface into the container. Linux handles hardware as files, and on a Raspberry Pi, the GPIO memory is located at /dev/gpiomem.
Using Docker Compose
If you are managing your deployments with docker-compose.yml (which is highly recommended for homelab setups), you can use the devices directive to map the GPIO interface from your host into the container.
Add this to your service configuration:
version: '3.8'
services:
my-gpio-app:
image: my-node-red-or-python-app:latest
restart: unless-stopped
# This is the magic line that passes the GPIO hardware into the container
devices:
- /dev/gpiomem:/dev/gpiomemUsing the Docker CLI
If you prefer to spin up your containers manually using the command line, you can achieve the exact same result using the --device flag:
docker run -d \
--name my-gpio-app \
--device /dev/gpiomem:/dev/gpiomem \
my-node-red-or-python-app:latestWhy /dev/gpiomem and not /dev/mem?
In older versions of the Raspberry Pi OS, developers often had to map /dev/mem to access GPIO. The problem is that /dev/mem gives access to all physical memory on the device, requiring your container to run as root.
/dev/gpiomem was introduced as a safer alternative. It restricts access purely to the GPIO registers, meaning your containerized scripts can run safely as a non-root user while still blinking LEDs, reading sensor data, or controlling relays.
Conclusion
By mapping /dev/gpiomem, you keep your Docker containers secure, maintain the principle of least privilege, and successfully bridge the gap between containerized software and physical hardware. Happy tinkering!
A quick tip for this post:
Make sure you create a folder at /assets/blog/pi-docker-gpio/ in your Next.js project and drop a relevant cover.jpg in there so your build doesn't fail!
Read Next
How to deploy a next.js application on docker hub
Explore how to deploy a next.js application on docker hub.
Internal TryHackMe Write-Up
The Internal room on TryHackMe is an hard challenge that let's you slip in the role of a penetration tester, where your objective is to perform a thorough penetration test
Daily Bugle TryHackMe Write-Up
The Daily Bugle room on TryHackMe is a hard room that requires you to compromise a Joomla CMS account.


