One of the nicest things about docker is reproducibility and containerisation. It is possible to run multiple applications which requires different environment on the same computer and make them live happily altogether. Although Raspberry Pi has ARMv7 instructions set, we still can run docker on it - we just need different images. One would be surprised there are some official images available on docker hub.
The configuration can be very simple - literally two commands in terminal, thanks to widely available devops tools such as docker-machine and ansible. Having this setup there won't be need to login to the RPi and perform any manual configuration per service anymore. Instead, services can be configured and deployed right from your computer.
If you don't have your Rasbperry configured yet refer to previous article for the initial setup.
Copy ssh key
To allow login without password using ssh key we need to transfer it to the RPi. This step can be skipped if it was done before.
Assuming that your pi is running with default login pi and password raspberry run this command and put password:
ssh-copy-id pi@192.168.42.111
Provisioning
There are some prerequiests for your local machine:
Get the playbook I've created:
And simply run
ansible-playbook provision-rpi.yml -i 192.168.42.111, --extra-vars "machine_name=myrpi"
Replacing IP address with your RPi location. Also, note that comma(,) at the end of the address is mandatory! Local name of the docker-machine can be configured via machine_name
variable, in the example it set to myrpi
First run can take some time, be patient.
This playbook is updating packages on your RPi, temporary monkey patching name of the OS, installs docker-machine and revert back changes of the name. Since ansible playbook is describing the final state there is no sin of running this playbook again - nothing will break. Be aware that you might want to remove existing docker-machine if it already exists or give it an another name
Sample output:
➜ ansible-playbook provision-rpi.yml -i 192.168.42.111, --extra-vars "machine_name=myrpi"
PLAY [RPi initial provisioner] ************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [192.168.42.111]
TASK [Remembering target host information] ************************************************************************************************************************
ok: [192.168.42.111]
TASK [Upgrade packages] *******************************************************************************************************************************************
[WARNING]: Could not find aptitude. Using apt-get instead
ok: [192.168.42.111]
TASK [Check what the new version is] ******************************************************************************************************************************
changed: [192.168.42.111]
TASK [Temporary monkey-patching os-release] ***********************************************************************************************************************
changed: [192.168.42.111]
TASK [Running docker-machine against 192.168.42.111] ***************************************************************************************************************
changed: [192.168.42.111 -> localhost]
TASK [Reverting OS name back in os-release] ***********************************************************************************************************************
changed: [192.168.42.111]
PLAY RECAP ********************************************************************************************************************************************************
192.168.42.111 : ok=7 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Done!
Let's try to run something against that docker on freshly backed pi
To make our docker client to run against the remote RPi daemon we must setup environment variables. It should be executed only once per session before any docker commands
➜ eval $(docker-machine env myrpi)
Let's see what version of the docker we are running:
➜ docker version
. . . . .
Server: Docker Engine - Community
Engine:
Version: 19.03.5
API version: 1.40 (minimum version 1.12)
Go version: go1.12.12
Git commit: 633a0ea
Built: Wed Nov 13 07:34:13 2019
OS/Arch: linux/arm
There are limited number of images available for arm32v7 on the docker hub. For demostration purposes I can run mediawiki:
➜ docker run -p 9999:80 -d arm32v7/mediawiki
Unable to find image 'arm32v7/mediawiki:latest' locally
latest: Pulling from arm32v7/mediawiki
c4f8e1e649d2: Pull complete
. . . . . .
Status: Downloaded newer image for arm32v7/mediawiki:latest
0041a9fbf8d9a3bc85a337eafbbf50e135b77705e4d663c4bfd72771b8935426
➜ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
22dfef415586 arm32v7/mediawiki "docker-php-entrypoi…" 26 seconds ago Up 23 seconds 0.0.0.0:9999->80/tcp lucid_ramanujan
As expected mediawiki is available via network:
Conclusion
Just 2 commands enable us to deploy our applications in the docker in a snap!