Docker Container Strategy
My homelab runs almost entirely on Docker, spread across three dedicated Debian VMs instead of installing containers directly on bare metal or on the NAS operating system itself. Each VM is a clean, disposable Docker host that can be snapshotted and backed up as a whole through Proxmox, and every service is defined declaratively as a Docker Compose file living under /docker-data/compose/<service>/. This keeps the setup portable, reproducible, and easy to document — if a host dies, restoring a VM snapshot brings every container definition back with it.
The three Docker hosts
- docker-host-pve — Debian VM on the main Proxmox server (PVE). This is the primary target for almost all container deployments, including my own images pulled from GHCR. Fully covered by Proxmox VM backups, so the whole host can be restored in one shot.
- docker-host-nas — Debian VM running directly on the Synology (via Virtual Machine Manager). Identical setup and folder structure to the PVE host, but used specifically for containers that need direct access to NAS storage volumes, such as media-processing tools that read and write large file libraries.
- docker-host-pve2 — Debian VM on the secondary Proxmox server (pve2), which lives in the study and is treated as a pure test/dev environment. New containers and compose setups get trialed here before being promoted to docker-host-pve.
Standardized layout
- /docker-data/compose/ — one subfolder per service, each containing its own
docker-compose.yml(and.envwhere needed). - /docker-data/volumes/ — persistent container data, kept outside the compose folders so it survives redeploys.
- /docker-data/backups/ — local backup staging before data is pulled into the wider backup chain.
- Same convention everywhere — because all three hosts follow this identical structure, moving a service between hosts or rebuilding a host from scratch is just a matter of copying the compose folder and running
docker compose up -d.
Own GitHub projects
- icloud-contacts-sync — syncs contact data between iCloud and other systems.
- calendar-sync — keeps calendars synchronized across sources.
- mvg-departures — pulls Munich public transport (MVG) departure data for local dashboards.
- wetter-api — a small weather API/worker pair, built from a custom GHCR image and updated automatically via Watchtower.
Infrastructure containers
- mosquitto-mqtt — central MQTT broker for smart-home and sensor messaging.
- grafana, prometheus, influxdb — the monitoring and metrics stack for dashboards and time-series data.
- healthchecks, uptime-kuma, cadvisor — service and container health/uptime monitoring.
- dyndns-updater — keeps DNS pointed at the home connection; my own project, see skoelle/dyndns-updater on GitHub.
- watchtower — automatically checks for and applies container image updates on a daily schedule.
- authelia, nginx-proxy-manager — authentication layer and reverse proxy for exposing internal services safely.
- postfix — internal mail relay used by other containers (e.g. Watchtower notifications) to send email.
- portainer — web UI for managing containers across hosts.
- exporters — Prometheus exporters for Fritz!Box, Zyxel switches, Nginx, and SNMP devices, feeding the Grafana/Prometheus stack.
Smart home containers
- Home Assistant — only used for homematicIP integration to mqtt.
Application containers
- SearXNG — self-hosted, privacy-respecting metasearch engine.
- Open WebUI — chat interface for locally hosted LLMs.
- Stirling PDF — self-hosted PDF toolkit for merging, converting and editing documents.
- ArchiveBox — personal web archiving of bookmarked pages.
- TubeSync / TubeArchivist [NAS] — download and archive YouTube content directly onto NAS storage; these run on docker-host-nas specifically because they need direct volume access to the Synology's disks.
Development tools
- Gitea — self-hosted Git server acting as a mirror of my GitHub repositories, giving me a local fallback and faster internal access.