Deploying Applications to Raspberry Pi with Docker Compose (from my Mac)
This blog post explains how to deploy applications from your Mac to a Raspberry Pi using Docker Compose. We'll use a simple Go web application as an example.
Prerequisites
A Raspberry Pi running RaspberryPi OS (deployment machine)
A Mac (development machine) - theoretically, this should work on any OS (on Windows, you can use WSL2)
Basic knowledge of Docker and SSH
1. Setting Up Docker on Raspberry Pi
First, we need to install Docker on the Raspberry Pi. Connect to your Pi and run these commands:
Adding Docker's Official GPG Key
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Adding Docker Repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
Installing Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Running Docker Without Sudo
To avoid using sudo for every Docker command:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
2. Setting Up SSH Access
Create and configure SSH keys on your Mac:
- Generate a new SSH key:
ssh-keygen -t rsa -f ~/.ssh/rpi_rsa
- Add the key to SSH agent:
ssh-add ~/.ssh/rpi_rsa
- Copy the public key to your Raspberry Pi:
ssh-copy-id -i ~/.ssh/rpi_rsa.pub username@raspberry-pi-hostname
- Create SSH config file (
~/.ssh/config
):
Host raspberry-pi-hostname
HostName raspberry-pi-hostname
PreferredAuthentications publickey
IdentityFile ~/.ssh/rpi_rsa
3. Creating Docker Remote Context
Set up a remote Docker context to manage Docker on the Raspberry Pi:
docker context create \
--docker host=ssh://username@raspberry-pi-hostname \
--description="Remote engine on Raspberry Pi" \
rpi-remote
Switch to the remote context:
docker context use rpi-remote
4. Example Application
Let's look at our example Go application that we'll deploy:
Main Application Code (main.go)
package main
import (
"log"
"net/http"
"os"
)
func main() {
var httpPort = os.Getenv("HTTP_PORT")
if httpPort == "" {
httpPort = "8080"
}
mux := http.NewServeMux()
mux.HandleFunc("/", func(response http.ResponseWriter, request *http.Request) {
response.Header().Add("Content-Type", "text/html;charset=utf-8")
response.Write([]byte("<h1>👋 Hello World 🌍</h1>"))
})
log.Println("🌍 http server is listening on: " + httpPort)
log.Fatal(http.ListenAndServe(":"+httpPort, mux))
}
Dockerfile
FROM golang:1.22.1-alpine as buildernext
WORKDIR /app
COPY main.go .
COPY go.mod .
COPY go.sum .
RUN go build
FROM scratch
WORKDIR /app
COPY --from=buildernext /app/tiny-service .
CMD ["./tiny-service"]
Docker Compose File (compose.yaml)
services:
web-app:
build:
context: .
dockerfile: Dockerfile
environment:
- HTTP_PORT=6066
ports:
- 6066:6066
5. Deploying the Application
With everything set up, deploy the application:
- Ensure you're using the remote context:
docker context use rpi-remote
- Deploy using Docker Compose:
docker compose up --build -d
use
--build
only if you want to rebuild the image.
The application will be built on your Raspberry Pi and deployed to your Raspberry Pi, accessible on port 6066.
Testing the Deployment
Access the application by opening a web browser and navigating to:
http://raspberry-pi-hostname:6066
You should see the "👋 Hello World 🌍" message.
Troubleshooting Tips
Verify your context is correct:
docker context ls
Check container status:
docker ps
View logs:
docker compose logs
Return to local context:
docker context use default
Conclusion
Using Docker Compose with a remote context provides a streamlined way to deploy applications to a Raspberry Pi (or any other server) from your Mac. This setup allows you to manage deployments remotely while maintaining a clean separation between development and deployment environments.