Docker revolutionizes how you run services on your Raspberry Pi by containerizing applications. Instead of installing each service directly on your Pi and dealing with dependency conflicts, Docker lets you run isolated containers that include everything an application needs. This guide will get Docker up and running on your Pi and teach you the essentials.
Prerequisites
Before starting, make sure you have:
- Raspberry Pi with Raspberry Pi OS installed and updated
- SSH access to your Pi
- Static IP address configured (from our previous guide)
- At least 2GB of free storage space
What is Docker and Why Use It?
Docker packages applications and their dependencies into containers that run consistently anywhere. For home lab enthusiasts, this means:
- Easy installation: Most services can be deployed with a single command
- Isolation: Each container runs independently without conflicts
- Easy updates: Pull a new container version without breaking your system
- Portability: Move your entire setup to new hardware easily
- Resource efficiency: Containers share the host OS kernel, using less resources than virtual machines
Step 1: Install Docker
Docker provides an official convenience script that handles the entire installation. Run these commands:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
The script will automatically detect your system and install the correct version. This takes about 2-3 minutes.
What's happening: The script adds Docker's repository, installs Docker Engine, and configures it to start automatically on boot.
Step 2: Add Your User to the Docker Group
By default, you need sudo to run Docker commands. Let's fix that:
sudo usermod -aG docker $USER
Important: You must log out and log back in (or reboot) for this to take effect:
sudo reboot
After reconnecting via SSH, verify you can run Docker without sudo:
docker --version
You should see something like: Docker version 24.0.7, build afdd53b
Step 3: Verify Docker Installation
Let's run Docker's test container to confirm everything works:
docker run hello-world
If Docker is working correctly, you'll see a message explaining what just happened. Docker downloaded a test image, created a container from it, ran it, and displayed the output.
Step 4: Install Docker Compose
Docker Compose lets you define and run multi-container applications using YAML files. It's essential for managing complex setups.
sudo apt install docker-compose -y
Verify the installation:
docker-compose --version
Note: Newer versions use docker compose (without the hyphen) as a plugin. Both work, but we'll use the traditional docker-compose syntax in this guide.
Understanding Docker Basics
Before we start running services, let's understand the key concepts:
Images: Read-only templates used to create containers. Think of them as the blueprint.
Containers: Running instances of images. These are your actual applications.
Volumes: Persistent storage for container data. Without volumes, data is lost when containers are removed.
Networks: Allow containers to communicate with each other and the outside world.
Docker Hub: The default registry where Docker images are stored and shared.
Essential Docker Commands
Here are the commands you'll use most often:
Working with containers:
docker ps # List running containers
docker ps -a # List all containers (including stopped)
docker start container_name # Start a stopped container
docker stop container_name # Stop a running container
docker restart container_name # Restart a container
docker rm container_name # Remove a stopped container
docker logs container_name # View container logs
docker exec -it container_name /bin/bash # Access container shell
Working with images:
docker images # List downloaded images
docker pull image_name # Download an image
docker rmi image_name # Remove an image
System management:
docker system df # Show Docker disk usage
docker system prune # Remove unused data (careful!)
docker stats # Real-time container resource usage
Step 5: Create a Docker Directory Structure
Let's set up an organized directory structure for your Docker containers:
mkdir -p ~/docker
cd ~/docker
For each service you run, create a subdirectory:
mkdir -p ~/docker/{portainer,nginx,pihole}
Why this matters: Keeping configs and data organized makes your setup easier to maintain and backup.
Step 6: Deploy Your First Real Container - Portainer
Portainer provides a web-based interface for managing Docker. It's perfect for beginners and still useful for experienced users.
docker volume create portainer_data
docker run -d \
-p 9000:9000 \
-p 9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
What each part does:
-d: Run in detached mode (background)-p 9000:9000: Map port 9000 on Pi to port 9000 in container--name portainer: Give the container a friendly name--restart=always: Automatically restart if it crashes or after reboot-v: Mount volumes for persistent data
Access Portainer by visiting http://your-pi-ip:9000 in your web browser.
First-time setup: Create an admin account when prompted. Choose a strong password.
Step 7: Understanding Docker Compose Files
Docker Compose uses YAML files to define your containers. Let's create a simple example for an Nginx web server:
cd ~/docker/nginx
nano docker-compose.yml
Add this content:
version: '3.8'
services:
nginx:
image: nginx:latest
container_name: nginx-test
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
Create a simple HTML file:
mkdir html
echo "<h1>Hello from Docker!</h1>" > html/index.html
Deploy it:
docker-compose up -d
Visit http://your-pi-ip:8080 to see your page.
Managing this container:
docker-compose down # Stop and remove
docker-compose up -d # Start
docker-compose restart # Restart
docker-compose logs # View logs
docker-compose pull # Update images
Step 8: Configure Docker for Better Performance
Let's optimize Docker for the Raspberry Pi:
Limit log file sizes to prevent filling your SD card:
sudo nano /etc/docker/daemon.json
Add this content:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Restart Docker:
sudo systemctl restart docker
Working with ARM-Specific Images
Raspberry Pi uses ARM architecture. Most popular images support ARM, but always check:
Look for these tags:
arm64v8/image-nameimage-name:latest(many auto-detect architecture)- Check the image's Docker Hub page for ARM support
Example: For Pi-hole, use:
docker pull pihole/pihole:latest
The official Pi-hole image supports ARM automatically.
Docker Best Practices for Raspberry Pi
Use bind mounts for config files: This makes editing easier without entering containers.
Always use restart policies: Add --restart=unless-stopped to keep services running after reboot.
Monitor resource usage: Use docker stats to ensure you're not overloading your Pi.
Update regularly: Pull new images monthly for security patches.
Backup your compose files: Keep your docker-compose.yml files in version control or backed up.
Use environment files: Store sensitive data like passwords in .env files instead of compose files.
Common Docker Workflows
Updating a container:
cd ~/docker/service-name
docker-compose pull
docker-compose up -d
docker image prune
Viewing logs:
docker logs -f container_name # Follow logs in real-time
docker logs --tail 100 container_name # Last 100 lines
Backing up container data:
docker run --rm \
-v container_volume:/source \
-v ~/backups:/backup \
alpine tar -czf /backup/backup.tar.gz -C /source .
Troubleshooting Common Issues
Container won't start:
- Check logs:
docker logs container_name - Verify port conflicts:
sudo netstat -tulpn | grep :PORT - Check disk space:
df -h
Permission denied errors:
- Ensure you're in the docker group
- Check volume mount permissions
- Try recreating the container
Out of disk space:
docker system prune -a # Remove all unused images and containers
docker volume prune # Remove unused volumes (careful!)
Slow performance:
- Check if you're running too many containers for your Pi's RAM
- Monitor with
htopanddocker stats - Consider using lighter alternatives or upgrading your Pi
Security Considerations
Don't expose management ports to the internet: Use a VPN to access Portainer and other management interfaces remotely.
Use strong passwords: Especially for any web interfaces.
Keep images updated: Old images may contain security vulnerabilities.
Use read-only volumes when possible: Add :ro to volume mounts that don't need write access.
Review container permissions: Avoid running containers as root unless necessary.
Next Steps
Now that Docker is running, you're ready to deploy real services:
- Set up a file server - Use Samba or NFS containers to share files
- Deploy a media server - Install Jellyfin or Plex for streaming
- Add Pi-hole - Block ads network-wide with a containerized DNS server
- Install monitoring - Set up Grafana and Prometheus to monitor your homelab
- Explore Portainer - Use the web interface to manage containers visually
Quick Reference Card
# Container lifecycle
docker run -d --name myapp myimage
docker stop myapp
docker start myapp
docker restart myapp
docker rm myapp
# Viewing information
docker ps
docker logs myapp
docker stats
docker inspect myapp
# Compose commands
docker-compose up -d
docker-compose down
docker-compose logs -f
docker-compose restart
# Cleanup
docker system prune
docker image prune
docker volume prune
Estimated time to complete: 30-45 minutes
Difficulty level: Beginner to Intermediate
Prerequisites: Completed Raspberry Pi setup guide
Docker is now your gateway to running countless services effortlessly. Each service we cover in future guides will leverage Docker to make installation simple and maintainable. Ready to deploy your first real service? Check out our Samba file server guide next!
