Raspberry Pi with Docker
I use Raspberry Pis to host services for my home network, with Docker to keep things manageable in containers. Each Pi has a USB SSD as its boot drive running Raspberry Pi OS.
There's often a bit of boilerplate I need to keep track of to set up a new one, so I am documenting all of the snippets here for my future self.
- Increase Swap Size
- Disable DHCP for Virtual Ethernet Interfaces
- Install Docker
- Make SSH Secure
- Managing Docker Compose
- Passwordless Sudo
- Overclocking
- Temperature and Speed
- Architecture Emulation
- Disable WiFi Power Saving
- Create a systemd Service
- Disable nftables
Increase Swap Size
If you're using an SSD as a boot drive, the default 100MB limit for Swap doesn't make sense. There is a great article here documenting how to change this, but the key bits are:
$ nano /etc/dphys-swapfile
Comment out CONF_SWAPSIZE
, since it is explicitly set to 100. Commenting it out makes the OS manage it automatically, and in my case made the swap size 2GB.
#CONF_SWAPSIZE=100
Then restart the Swap service:
$ /etc/init.d/dphys-swapfile restart
You can use free -m
or htop
to verify the change.
Disable DHCP for Virtual Ethernet Interfaces
Docker creates a lot of virtual ethernet interfaces, and they all start requesting IP addresses and it all ends very badly (the Pi will drop off the network at some point after being on for a while).
The fix is to tweak the DHCP config:
$ nano /etc/dhcpcd.conf
Add the following to the very top of the file:
denyinterfaces veth*
Then restart the DCHP daemon:
$ systemctl daemon-reload
$ systemctl restart dhcpcd
Install Docker
The best thing to do to set up Docker for the first time is the following:
$ apt-get update
$ apt-get upgrade
$ reboot
The reboot at the end is crucial, as I found some Docker installation errors when not rebooting.
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sh get-docker.sh
$ reboot
That last reboot is just for good measure - it's probably not necessary. Then you're good to go!
Make SSH Secure
To make SSH more secure, we should disable username/password auth.
$ nano /etc/ssh/sshd_config
Comment out every entry, so the file only has the following uncommented entries (you could delete the file contents and replace it with the below, but then you lose all of the documentation):
Include /etc/ssh/sshd_config.d/*.conf
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM no
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
Then restart SSH:
$ systemctl restart ssh
Managing Docker Compose
To deploy a service with Docker Compose, go to the directory containing the docker-compose.yml
file, then:
$ docker compose up -d
To update a Docker compose service:
$ docker compose pull
To remove the service:
$ docker compose down
Passwordless Sudo
To enable passwordless sudo:
$ visudo /etc/sudoers.d/010_pi-nopasswd
Then change the content to:
pi ALL=(ALL) ALL
Where pi
is the username you're logging in with.
Overclocking
If you have adequate active cooling set up around your Pi, you can go for glory with the CPU clock speed:
$ nano /boot/config.txt
#uncomment to overclock the arm. 700 MHz is the default.
over_voltage=6
arm_freq=2147
This clocks the CPU up to 2.1GHz.
Temperature and Speed
Measure the current CPU frequency in Hz:
vcgencmd measure_clock arm
frequency(48)=1800457088
Get the CPU temperature:
$ vcgencmd measure_temp
temp=59.4'C
Get the CPU temperature, but update live:
$ watch --interval 0.1 -- 'vcgencmd measure_temp'
It's also possible to read this from a file:
$ cat /sys/class/thermal/thermal_zone0/temp
53069
Here's some Python code to read it as degrees celsius:
with open('/sys/class/thermal/thermal_zone0/temp') as f:
current_cpu_temp = float(f.read()) / 1000
Architecture Emulation
If you need to run non-ARM Docker containers, you can install an emulation layer. This article has an in-depth explanation: Run AMD64 Docker Images On An ARM Computer
The below command enables amd64
support via the following library: https://github.com/tonistiigi/binfmt
$ docker run --privileged --rm tonistiigi/binfmt --install amd64
AMD64 containers will now run, just much more slowly than on the native hardware.
Disable WiFi Power Saving
The WiFi chip, by default uses power saving. To check the status of this, use the following command:
$ iw wlan0 get power_save
Power save: on
To disable WiFi Power Saving permanently, use the following command:
$ nmcli con mod preconfigured wifi.powersave disable
Note that this will not disable power saving immediately, but at the next boot.
Create a systemd Service
First, create the service definition:
$ nano /etc/systemd/system/example.service
Example, with placeholders for description
, user
, working directory
and command
.
[Unit]
Description=<description>
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=<user>
WorkingDirectory=<working directory>
ExecStart=<command>
[Install]
WantedBy=multi-user.target
The service is enabled with:
$ systemctl enable example.service
And started with:
$ systemctl start example.service
To check the status of the service:
$ systemctl status example.service
And to get logs from the service if it errors:
$ journalctl -u example.service
Disable nftables
This was a one-time problem and should be considered "deprecated" from the guide.
I ran into an issue where Raspberry Pi OS installed an update which bricked the Docker daemon, because the update forced a switch from iptables
to nftables
(Docker wanted iptables
). I ended up fixing it by forcing the use of iptables
, then re-installing docker.
$ update-alternatives --set iptables /usr/sbin/iptables-legacy
$ update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
$ update-alternatives --set arptables /usr/sbin/arptables-legacy
$ update-alternatives --set ebtables /usr/sbin/ebtables-legacy
🏷️ docker pi swap power file cpu raspberry install ssh temperature wifi containers boot os dhcp
Please click here to load comments.