$docker.recipes
·12 min read

Self-Hosting on a Raspberry Pi with Docker Compose: What Works and What Doesn't

A practical guide to running Docker Compose on a Raspberry Pi — which services run well, which struggle, and how to optimize for ARM and limited resources.

raspberry-piarmself-hostingdocker-composehomelab

01The $80 Home Server

My self-hosting journey started with a Raspberry Pi 4 with 4GB of RAM and a 128GB microSD card. Total cost: about $80. It's not the most powerful server, but it ran Pi-hole, Vaultwarden, Uptime Kuma, and a few other lightweight services without breaking a sweat. A year later, I upgraded to a mini PC for my main stack, but I still run a Raspberry Pi as a secondary server for network services and monitoring. The Pi 5 with 8GB is a meaningful upgrade — it can handle 10-15 services comfortably. This guide shares what I learned about running Docker on ARM hardware: which services work well, which struggle, and the optimizations that matter most on resource-constrained hardware.

02Initial Setup for Docker on Raspberry Pi

Start with Raspberry Pi OS Lite (64-bit). The 64-bit version is important — many Docker images don't have 32-bit ARM builds, and the 64-bit OS runs them natively.
[terminal]
1# Install Docker
2curl -fsSL https://get.docker.com | sh
3sudo usermod -aG docker $USER
4
5# CRITICAL: Use an SSD instead of microSD
6# MicroSD cards are slow and wear out from Docker I/O
7# Connect a USB SSD and move Docker's data directory:
8sudo systemctl stop docker
9sudo rsync -a /var/lib/docker/ /mnt/ssd/docker/
10# Add to /etc/docker/daemon.json:
11# { "data-root": "/mnt/ssd/docker" }
12sudo systemctl start docker

Running Docker on a microSD card works but is slow and will wear out the card. An external USB SSD is the single most impactful upgrade for a Raspberry Pi server — expect 5-10x faster container starts and much better database performance.

03Services That Run Great on Raspberry Pi

These services run perfectly on a Pi 4 (4GB) or Pi 5 (8GB) with minimal resource usage: Pi-hole: Uses about 50MB RAM. The perfect Pi application — filter ads and trackers for your entire network. Vaultwarden: Under 30MB RAM. Password management for unlimited users. Uptime Kuma: About 80MB RAM. Monitor all your services from the Pi. WireGuard VPN: Minimal CPU and RAM. The kernel module handles encryption efficiently even on ARM. Homepage dashboard: About 100MB RAM. Your central service dashboard. Nginx Proxy Manager: About 150MB RAM. An easy reverse proxy with a web UI if you find Traefik too complex. AdGuard Home: About 60MB RAM. An alternative to Pi-hole with a more modern UI. Unbound: Under 20MB RAM. A recursive DNS resolver for maximum privacy alongside Pi-hole. All of these have official ARM64 Docker images and run without any ARM-specific configuration.

04Services That Struggle

Some services need more resources than a Pi can comfortably provide: Nextcloud: Works but is noticeably slow, especially the web interface. File sync is fine, but don't expect snappy page loads. Needs at least 4GB RAM to avoid swapping. Jellyfin: Works for direct play (no transcoding). Hardware transcoding is limited on Pi — don't expect to transcode 4K video. If all your clients can direct play your media formats, it's usable. GitLab: Too heavy. Use Gitea or Forgejo instead — they use a fraction of the resources and provide 90% of the features. Prometheus + Grafana: Grafana is fine, but Prometheus with many scrape targets can overwhelm a Pi's I/O. Consider using VictoriaMetrics as a lighter alternative. Any AI/ML workload: LLMs and image generation need far more RAM and CPU than a Pi offers. Even small models are painfully slow without GPU acceleration.

05ARM and Resource Optimization Tips

Running Docker on a Pi requires more attention to resource usage: Always use Alpine images when available. The smaller image size means faster pulls over limited bandwidth and less storage usage. Set memory limits on every container. On a 4-8GB device, a single memory leak can bring down everything. Be conservative — start with 256MB limits and increase only if needed. Disable services you're not actively using. On a Pi, every idle service consumes resources that could improve the performance of services you actually use. Use docker compose down instead of docker compose stop for services you won't need for a while. Stop keeps the container in memory; down removes it completely. Monitor with docker stats to understand your actual resource usage. On my Pi 5 running 8 services, typical RAM usage is about 2.5GB of 8GB — plenty of headroom. Browse our homelab category for lightweight service configurations optimized for self-hosting, many of which work perfectly on Raspberry Pi hardware.

About the Author

Frank Pegasus

DevOps engineer and self-hosting enthusiast with over a decade of experience running containerized workloads in production. Creator of docker.recipes.