Most homelabs end up running the same way: a Pi-hole for DNS, maybe Home Assistant, a media server, Nextcloud, a handful of small tools you found on a weekend — and every single one of them wants a different Python version, a different Node version, or a package that conflicts with something else already on the box. Docker exists to make that problem disappear. Each service runs in its own isolated container with its own dependencies, and your host OS only ever needs Docker itself installed. This is the install, the homelab-specific configuration most tutorials skip, and a complete command cheatsheet for everyday use.
Info: What This Covers
Docker Engine + Compose on Ubuntu/Debian, the two settings every homelab should change before running anything long-term (log rotation and storage location), a working Compose example, and a full command reference.
Installing Docker on Ubuntu / Debian
Skip the Ubuntu repo's docker.io package — it lags months behind. Install straight from Docker's own apt repository instead, which is what gets you the current Engine plus the Compose v2 plugin.
On Debian, swap ubuntu for debian in both URLs above — the rest of the command is identical.
Run Docker Without sudo
Warning: What That Group Actually Grants
Membership in the docker group is root-equivalent — anyone in it can mount the host filesystem into a container and read or write anything root can. Fine for your own single-user homelab box; don't add shared or low-trust accounts to it.
Start Docker on Boot
Configuring Docker for a Homelab
The default settings are built for a laptop running Docker for an afternoon, not a box running twenty containers for two years. Two changes matter before you put anything real on it.
1. Cap Container Logs
By default, Docker's json-file log driver has no size limit. A chatty container — Home Assistant with debug logging on, or a media server transcoding daily — will quietly fill your disk over a few months. Nothing crashes loudly; you just wake up to a full root partition.
Save that as /etc/docker/daemon.json (create the file if it doesn't exist), then restart Docker. This caps every container's logs at 3 files of 10MB each — old data ages out automatically instead of accumulating forever. It only applies to containers created after the change, so existing ones need a recreate (docker compose up -d -force-recreate) to pick it up.
2. Move Docker’s Storage Off the Boot Drive
Most homelab boxes boot from a small SSD and keep bulk storage on a separate drive or NAS mount. Docker defaults to /var/lib/docker on whatever disk that is — worth relocating before your image and volume data eats the drive your OS needs to boot.
Add data-root to the same daemon.json from step one:
Docker Compose: Your First Homelab Stack
Almost nobody runs docker run by hand for long — a docker-compose.yml file that describes the whole service (image, ports, volumes, restart policy) in one place is the homelab standard. Here's Portainer, a web UI for managing containers, as a first real stack:
Note: docker compose, Not docker-compose
Older tutorials use the standalone docker-compose (hyphen) Python tool, which is deprecated. The docker-compose-plugin installed above gives you docker compose (space) as a Docker subcommand instead — same YAML file, different invocation. If a guide's commands fail with "command not found," this is usually why.
The Cheatsheet
Container Lifecycle
Images
Volumes & Networks
Docker Compose
Cleanup & Disk Space
Inspecting & Debugging
Common Homelab Gotchas
- ●restart: unless-stopped missing from a compose file — the #1 reason a service doesn't come back after a power cut or reboot. Without it, Docker's default restart policy is none.
- ●Permission denied on /var/run/docker.sock right after usermod -aG docker — the group change needs a fresh login session; newgrp docker works in the current shell but not for services started another way.
- ●Bind mounts vs. named volumes — a bind mount (- /opt/appdata/pihole:/etc/pihole) puts data in a plain folder you can back up directly; a named volume (- pihole_data:/etc/pihole) is Docker-managed and lives under /var/lib/docker/volumes, which is easy to forget about until a backup script misses it.
- ●Port conflicts on the host — two containers can't both bind host port 80. Map each to a unique host port (8080:80, 8081:80) or put a reverse proxy (Traefik, Caddy, Nginx Proxy Manager) in front once you're running more than a couple of web services.
Warning: If Your Router Port-Forwards to This Box
Don't publish a container's ports straight to 0.0.0.0 on a box reachable from the internet without a reverse proxy and TLS in front of it. -p 8080:80 is fine on your LAN; forwarded through your router with no proxy, it's an unauthenticated service exposed to the entire internet.
Everything above gets a single Docker host running reliably. The natural next question, once you're comfortable with it, is what changes when you need more than one host — that's what container orchestration (Kubernetes, or the lighter-weight Docker Swarm) actually solves.
For how that comparison actually plays out, see Kubernetes vs Docker Swarm. Our live Kubernetes and DevOps batches both start from exactly this — a single Docker host — before building up to production-grade, multi-node deployments.
Go Further
- Kubernetes vs Docker Swarm: Which to Learn in 2026?
What changes once one Docker host isn’t enough
- CKA Free Mock Exam — 2 × 30 scenario questions
Instant results, no account needed
- Live Kubernetes Training — CKA & CKAD in 45 days
Hands-on labs on real clusters, starting from Docker fundamentals
- Live DevOps Training — CI/CD, Terraform & GitOps
Docker and Compose are week-one material
Ready to Start Your Cloud Journey?
Live batches Mon–Sat — Azure 9–10 AM IST (started 3 august 2026 — join in progress) · AWS 10:30–11:45 AM IST (starts 31 august 2026). Hands-on labs, exam prep, and community support.