Peripherals from runc containers
I have been lately working on a minimal container runtime targeting embedded Linux to deploy the service and app layer on a large number of devices as an addition to our current way of delivering new firmwares and reflashing them. I am willing to use OCI bundles internally and willing to expose a custom image format, a minimal manifest, in order to represent image metadata and runtime attributes.
In this article, I am going to give you a sneak peak of how to work with low-level peripheral devices such to do GPIO, SPI, PWM, I2C, etc from a runc container. Note that the sample pre-built binaries are targeting Linux/ARMv7, if you are deploying to a board with a different architecture, you need to build the binaries from the source.
The current official Raspbian distributions doesn’t come with cgroups out of the box. So in order to run runc, you need to rebuild the kernel with the required bits or can reuse one of the hypriot’s Docker-supporting Raspberry Pi images and install runc.
Blink
We will use a minimalistic LED blinking sample from the rpio package. First, connect an LED to the GPIO pin 10.

If you are running hypriot’s image or have Docker daemon installed on the host, you can grab the equivalent Docker image and build an OCI bundle yourself. Otherwise, see bundles/armv7/blink for a prebuilt bundle.
$ docker pull rakyll/blink
$ docker create --name tmpblink rakyll/blink
$ mkdir -p ~/bundles/blink/rootfs
$ docker export tmpblink | tar -C ~/blink/rootfs -xf -
In order to do GPIO, we are going to read and write to /dev/mem from the container. We need to create a mount point for /dev and specify /dev/mem as a device. The blinker process also requires CAP_SYS_RAWIO and CAP_DAC_OVERRIDE Linux capabilities. See the config.json and runtime.json at bundles/armv7/blink for reference. Once you have the rootfs and the configuration, you can run the container.
$ runc start ~/bundles/blink
It will toggle the LED for a couple of times and quit.
The Rainbow
The rainbow bundle will draw a rainbow on an LED strip. I am using APA-102 LEDs driven by the Raspberry Pi’s SPI bus.
$ docker pull rakyll/rainbow
$ docker create --name tmprainbow rakyll/rainbow
$ mkdir -p ~/bundles/rainbow/rootfs
$ docker export tmprainbow | tar -C ~/rainbow/rootfs -xf -
bundles/armv7/rainbow contains the minimal configuration to mount /dev and specify /dev/spidev0.0 as a device. Run the container.
$ runc start ~/bundles/rainbow