Docker Compose is the homelab standard for declaring multi-container applications in YAML versioned beside
README files and .env secrets. If you have been running one-off docker run commands, Compose converts
fragile shell history into reproducible stacks you can redeploy after hardware failure. This beginner guide
explains project structure, service keys, networks and volumes, environment files, common commands, security
basics, how Compose interacts with reverse proxies, backups, and first troubleshooting steps—without assuming
prior orchestration experience.
Prerequisites
Install Docker Desktop or Docker Engine on Linux with the Compose plugin (docker compose version). Learn
basic Docker concepts: images, containers, layers, and registries. Create a working directory per app, e.g.
~/docker/whoami. Rootless Docker is optional advanced topic; this guide assumes standard Linux install.
Anatomy of docker-compose.yml
Compose file version 3+ (Compose Specification) defines services, networks, volumes, and optional configs
/secrets. A minimal service:
services:
web:
image: nginx:alpine
ports:
- "8080:80"
restart: unless-stopped
ports publishes container port 80 to host 8080. restart: unless-stopped survives reboots. Run docker compose up -d
from the directory containing the file; -d detaches.
Volumes and persistence
Containers are ephemeral; data in /tmp inside dies on remove. Bind mounts map host paths:
volumes:
- ./html:/usr/share/nginx/html:ro
Named volumes survive docker compose down without -v:
volumes:
app_data:
services:
db:
image: postgres:16
volumes:
- app_data:/var/lib/postgresql/data
Homelab databases and config dirs should always use volumes you backup.
Networks
Default bridge isolates stacks unless you connect them. Create shared proxy network once:
docker network create proxy
Then attach services:
networks:
proxy:
external: true
Services on the same network resolve each other by service name http://web:80.
Environment and secrets
Use .env for non-secret defaults (TZ=America/New_York). Never commit real passwords; reference ${POSTGRES_PASSWORD}
in compose and keep .env out of git via .gitignore. Docker secrets (Swarm) are rare in homelabs; prefer
external vault or restricted .env permissions.
Daily commands
docker compose up -d deploy, docker compose pull update images, docker compose logs -f service tail logs,
docker compose ps status, docker compose down stop without deleting volumes, docker compose exec service sh
shell inside. Changes to compose require up -d again to recreate containers when necessary.
Security notes
Pin image tags, not only latest. Drop capabilities where possible. Avoid mounting docker.sock into random
containers. Read image README for PU ID/PGID (LinuxServer images). Scan exposed ports with your router; prefer
reverse proxy plus VPN over wide port forwards.
Backup
Back up compose directory from git and backup named volumes and bind mounts. Export with docker run --rm -v vol:/data -v $(pwd):/b alpine tar czf /b/vol.tgz -C /data ..
Reverse proxy context
Compose stacks expose internal ports; Traefik labels on services automate public HTTPS. Pattern: all app services
join proxy network, only Traefik publishes 443.
Troubleshooting
Port already allocated: change host port or stop conflicting service. Cannot connect to service:
wrong network or service name typo. Permission denied on bind mount: match UID in container docs. YAML errors:
validate indentation with docker compose config.
Key takeaways
Compose turns homelab experiments into maintainable infrastructure. One folder per stack, version control YAML, external proxy network, pinned tags, and volume backups are habits that prevent painful rebuilds.
Homelab operators should treat documentation as part of the deployment: record image tags,
volume paths, environment variables, and the exact Compose file revision in your internal wiki
or git repository. When you rebuild the host six months later, those notes prevent guesswork
about which UID owned a bind mount or which DNS name the reverse proxy expected. Version-control
your stack directory and review diffs before docker compose up -d, especially when labels or
network names change.
Capacity planning remains underrated in small labs. Monitor CPU, memory, disk I/O, and network utilization for a full week under normal household load before declaring hardware sufficient. Burst workloads—library scans, backup deduplication, VPN throughput tests, or 4K transcodes—often define minimum specs more than idle dashboards. Leave headroom for OS updates and one misbehaving container without cascading failures across unrelated services.
Change management applies even when you are the only administrator. Take volume snapshots or
export application backups before major upgrades. Roll back by restoring the previous Compose
file and pinned image digest, not by improvising latest tags under pressure. If you integrate
with Home Assistant, Authentik, or Authelia later, note which services assumed anonymous LAN
access so you can tighten authentication deliberately rather than breaking automations overnight.
Network segmentation pays dividends when a guest Wi-Fi VLAN, IoT subnet, and management LAN coexist. Place management UIs on administrative networks, expose only reverse-proxied HTTPS endpoints where required, and default-deny east-west traffic between VLANs except established flows you document. Logs sent to Loki or a centralized syslog host make correlating reverse-proxy errors with container restarts far faster than SSHing into each machine during an incident.
Homelab operators should treat documentation as part of the deployment: record image tags,
volume paths, environment variables, and the exact Compose file revision in your internal wiki
or git repository. When you rebuild the host six months later, those notes prevent guesswork
about which UID owned a bind mount or which DNS name the reverse proxy expected. Version-control
your stack directory and review diffs before docker compose up -d, especially when labels or
network names change.
Capacity planning remains underrated in small labs. Monitor CPU, memory, disk I/O, and network utilization for a full week under normal household load before declaring hardware sufficient. Burst workloads—library scans, backup deduplication, VPN throughput tests, or 4K transcodes—often define minimum specs more than idle dashboards. Leave headroom for OS updates and one misbehaving container without cascading failures across unrelated services.
Change management applies even when you are the only administrator. Take volume snapshots or
export application backups before major upgrades. Roll back by restoring the previous Compose
file and pinned image digest, not by improvising latest tags under pressure. If you integrate
with Home Assistant, Authentik, or Authelia later, note which services assumed anonymous LAN
access so you can tighten authentication deliberately rather than breaking automations overnight.
Network segmentation pays dividends when a guest Wi-Fi VLAN, IoT subnet, and management LAN coexist. Place management UIs on administrative networks, expose only reverse-proxied HTTPS endpoints where required, and default-deny east-west traffic between VLANs except established flows you document. Logs sent to Loki or a centralized syslog host make correlating reverse-proxy errors with container restarts far faster than SSHing into each machine during an incident.
Homelab operators should treat documentation as part of the deployment: record image tags,
volume paths, environment variables, and the exact Compose file revision in your internal wiki
or git repository. When you rebuild the host six months later, those notes prevent guesswork
about which UID owned a bind mount or which DNS name the reverse proxy expected. Version-control
your stack directory and review diffs before docker compose up -d, especially when labels or
network names change.
Capacity planning remains underrated in small labs. Monitor CPU, memory, disk I/O, and network utilization for a full week under normal household load before declaring hardware sufficient. Burst workloads—library scans, backup deduplication, VPN throughput tests, or 4K transcodes—often define minimum specs more than idle dashboards. Leave headroom for OS updates and one misbehaving container without cascading failures across unrelated services.