Dockerized Development on a Raspberry Pi

Seng Lin Shee
4 min readAug 19, 2020
Photo by Harrison Broadbent on Unsplash

TL;DR

  1. An example of using a headless development environment on a Raspberry Pi using Visual Studio Code and Docker is shown.
  2. Docker containers allows reproducible development environments that is agnostic to the distribution of the Raspberry OS.
  3. Similar to most cloud native apps, Docker creates artifacts that are executable on any Docker-enabled Raspberry Pi irrespective of the OS distribution and setup.

Development Container

VS Code connects directly to a Docker server on the Raspberry Pi

So, I finally got myself a Raspberry Pi 4 a couple of weeks ago to try out some IoT projects and I wanted to integrate what I learned from my professional career to my personal pet projects.

The most straight forward way to get a Hello World running is to plug in a display, keyboard and mouse, and to use the Python editor that comes preinstalled on the Raspberry Pi.

However, I would like to use a framework whereby I can build and share more complicated projects in the future.

The trend for code development in a container has picked up. Examples include OpenShift CodeReady Workspaces and Github Codespaces. Also, there are already quite a few Raspberry Pi projects out there that have been Dockerized!

Why Remote Docker

  1. There is no need to set up peripherals on the device itself. You will be able to work on your personal development machine that you are used to.
  2. A Dockerized setup makes development of multiple projects on the device more manageable
  3. It also enables better sharing and collaboration with a wider audience
  4. We can reuse the common toolset of non-Raspberry Pi projects

You may argue that Python has several tools (e.g. pipenv) to create virtual environments for different projects. Then again, this depends on how you would like to manage projects on your Raspberry Pi. If you are thinking of working with Python, NodeJS, Java and even .NET Core at some point, you probably should be thinking outside of the Python tool chain (or any other framework dependent tool chain for that matter). Docker (at least for now), offers that abstraction, albeit at a performance / capability cost.

Setting up Docker on The Raspberry Pi

Let’s get going. I am assuming you will have set up your Raspberry Pi with

  1. Network enabled (WIFI / Ethernet) with a reachable DNS name / IP address.
  2. A login username and password

Once you have done the above, here are some snippets to install Docker (assuming you are logged in as pi and are using Raspbian/Ubuntu).

$ sudo apt-get update && sudo apt-get upgrade
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ sudo usermod -aG docker pi

Setting Up Visual Studio Workspace on The Development Machine

Install Visual Studio Code, Docker and the Remote Container extension on your development machine.

  1. Visual Studio Code
  2. Remote-Containers extension for Visual Studio Code
  3. Docker

Here is a workspace template to remotely connect to Docker on the Raspberry Pi. Download it and open the folder with Visual Studio Code on your development machine.

$ git clone git@github.com:senglin/python-rpi4-workspace.git
$ cd python-rpi4-workspace
$ code . # assuming you have set up this shortcut for VS Code

Modify the .vscode/settings.json file to match the location of your Raspberry Pi.

{
"docker.host": "ssh://pi@raspberrypi"
}

This step also assumes that you have set up ssh certificate credentials for your development machine to log in to the Raspberry Pi.

Modify the .devcontainer/devcontainer.json file if necessary to change the source mount location of your project. By default, I choose the home directory of the pi user.

{
...
"workspaceMount": "source=/home/pi,target=/workspace,type=bind,consistency=cached",
...
}
Reopen a project in a container

Click on the quick actions Status Bar item in the lower left corner.

Select Remote-Containers:Reopen in Container. This step will take awhile as VS Code will connect to the Docker server, and Docker images and the required packages will be downloaded and installed.

Once completed, you should be able to bring up a terminal to work within the container on the Raspberry Pi.

Build and Deploy Hello World

Here’s the easiest part, if everything has been smooth sailing so far. I have shared a Dockerized Hello World service written in Python 3 / Flask. This project showcases

  1. Usage of docker for deploying Raspberry Pi applications
  2. Usage of pipenv for Raspberry Pi Python projects. View the Dockerfile for implementation details.

While within the remote terminal on the Raspberry Pi, execute the following to clone and build the Hello World service.

$ git clone git@github.com:senglin/rpi-helloworld.git
$ cd rpi-helloworld
$ docker build -t rpi-helloworld .
$ docker run --rm -P rpi-helloworld

Determine the forwarded ports on the Raspberry Pi by typing this in the command line:

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a641ab7e24d4 rpi-helloworld "/usr/bin/entry.sh p…" 17 seconds ago Up 13 seconds 0.0.0.0:32780->8080/tcp festive_bhabha

From your development machine, bring up a different terminal and access the port on the Raspberry Pi using the DNS or ip address of your Raspberry Pi

$ curl raspberrypi:32780
{"message": "Hello World!"}

Conclusion

We have built and executed a Python 3 project using Docker and via a remote connection from a development machine.

What else can you think of that utilizes such setup for IoT projects? Are there better ways to manage projects and to enable sharing/code collaboration between individuals that have different devices, distributions, use cases and environments?

I will be building on top of this work as I explore more elaborate IoT use cases. So, stay tuned.

--

--

Seng Lin Shee

Love understanding how different pieces can make something beautiful. Still comprehending that building software is part engineering, art and social science.