Why Docker in a Homelab
Docker containers are the perfect fit for homelab services. They're lightweight, isolated, easy to deploy, and can be managed with version-controlled configuration files. Instead of installing software directly on your host (which leads to dependency conflicts and hard-to-reproduce setups), you run it in a container with everything it needs bundled in.
For someone coming from a Windows/VM-heavy background, Docker feels different but powerful. Think of it as a lightweight VM that shares the host kernel instead of virtualizing hardware.
Getting Started with Docker
On Linux (Ubuntu Server is my go-to for Docker hosts):
curl -fsSL https://get.docker.com | sh
Add your user to the docker group to avoid using sudo:
sudo usermod -aG docker $USER
On Windows, Docker Desktop works but uses a Linux VM under the hood. For production-style homelab setups, run Docker on a Linux host or in a Linux VM.
Essential Docker commands:
docker ps-- List running containersdocker images-- List downloaded imagesdocker pull nginx:latest-- Download an imagedocker run -d --name webserver -p 8080:80 nginx-- Run a container in detached modedocker logs webserver-- View container logsdocker stop webserver-- Stop a containerdocker rm webserver-- Remove a stopped containerdocker volume ls-- List persistent volumesdocker network ls-- List networks
docker-compose: Your Best Friend
Managing individual containers quickly becomes unwieldy. docker-compose lets you define multi-container applications in a single YAML file:
version: '3.8'
services:
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
Deploy with docker-compose up -d. Manage with docker-compose down, docker-compose restart, docker-compose logs.
Essential Homelab Services
Here are services every homelab should run:
- Portainer -- Web-based Docker management GUI. Makes container management visual and easy
- nginx-proxy + letsencrypt -- Reverse proxy with automatic SSL certificate management. Route all your services through a single port (443)
- Pi-hole -- Network-wide ad blocking. Run in a container with dnsmasq integration
- Home Assistant -- Home automation platform. Integrates with IoT devices, lighting, sensors
- Grafana + Prometheus -- Monitoring and visualization. Track CPU, memory, disk, network across all lab machines
- Nextcloud -- Self-hosted file sync and sharing. Dropbox/Google Drive alternative
- Vaultwarden -- Lightweight Bitwarden password manager. Store all your credentials securely
- Immich -- Self-hosted photo management. Google Photos alternative with facial recognition
- Headscale -- Open-source Tailscale control server. Manage mesh networking in your lab
- Gitea -- Lightweight Git server. Host your own code repositories
Reverse Proxy Setup
A reverse proxy is essential for homelab organization. Instead of accessing services on different ports (homeassistant:8123, nextcloud:8080, vaultwarden:82), you route everything through domain names:
homeassistant.yourdomain.com→ Home Assistant containernextcloud.yourdomain.com→ Nextcloud containervaultwarden.yourdomain.com→ Vaultwarden container
Use nginx-proxy with the jrcs/letsencrypt-nginx-proxy-companion for automatic SSL. All you need is a wildcard DNS record pointing to your server and the right Docker labels on each container.
Storage and Volumes
Docker containers are ephemeral -- when they stop, data inside them disappears. Use volumes for persistent storage:
- Named volumes -- Managed by Docker, stored in /var/lib/docker/volumes. Good for database data
- Bind mounts -- Map a host directory to a container directory. Easier to backup and manage
- Host paths -- Direct mount of a specific path. Most flexible but requires knowing your filesystem layout
Best practice: use bind mounts for configuration files and named volumes for database data. This makes backups straightforward -- just copy the host directories.
Networking in Docker
Docker creates a default bridge network, but for homelab services, create a custom network:
docker network create homelab
Then attach all your containers to it. Containers on the same network can reach each other by container name (DNS resolution is automatic):
docker run -d --name pihole --network homelab pihole/pihole:latest
Use host networking mode for services that need to bind to specific host ports (like VPN servers) or when you want maximum performance without NAT overhead.
Backup and Recovery
- Back up volumes -- Use
docker run --rm -v container_name:/data -v $(pwd):/backup alpine tar czf /backup/data.tar.gz -C /data . - Back up docker-compose files -- Store them in Git. Your compose files are your infrastructure as code
- Snapshot your Docker host -- If running on Proxmox or Hyper-V, take VM snapshots before major changes
- Use Portainer backup -- Portainer has a built-in backup feature that captures all stack configurations