SKIP TO CONTENT
FL1GHT5 Network

Apr 11, 2024 · Linux & Servers / Beginner · ~3 MIN READ

Docker Compose for Home Labs

Deploy services cleanly, store persistent data correctly, and upgrade without losing everything — the prerequisite for most self-hosted apps.

Who This Is For

Beginner to intermediate. This is the prerequisite article for most self-hosted app guides on this site.

Think of it like a packing list for moving house. Instead of remembering every box and where it goes, you write the list once, and unpacking looks the same no matter which new place you’re moving into.

What You’ll Build

Understand images, volumes, and networks well enough to deploy any Compose-based service cleanly, with data that survives an upgrade.

Prerequisites

  • A Linux host (VM, LXC, or bare metal) with Docker Engine installed
  • Basic terminal familiarity

Architecture

A predictable directory layout keeps a growing homelab sane:

$ mkdir -p /opt/stacks/uptime-kuma
$ mkdir -p /opt/stacks/nextcloud
$ mkdir -p /opt/stacks/vaultwarden

Anatomy of a compose.yaml

Every service block generally needs: image, container_name, ports, environment, volumes, networks, and restart.

$ services:
$   uptime-kuma:
$     image: louislam/uptime-kuma:1
$     container_name: uptime-kuma
$     ports:
$       - "3001:3001"
$     volumes:
$       - ./data:/app/data
$     restart: unless-stopped

Named Volumes vs. Bind Mounts

  • Named volume, Docker manages the storage location; simpler, portable between hosts
  • Bind mount, you choose the exact host path; easier to back up directly, easier to inspect

Environment Variables and Secrets

Keep secrets in a .env file next to the compose.yaml, restrict its permissions, and never paste its contents into a screenshot or public repo.

$ chmod 600 .env

Everyday Commands

$ docker compose up -d
$ docker compose logs -f
$ docker compose pull
$ docker compose down
$ docker compose ps

The Upgrade Workflow

  1. Read the release notes for breaking changes
  2. Back up the data directory
  3. Pull the new image
  4. Recreate the stack
  5. Test the service actually works before moving on

Security & Backup Notes

  • Application data must live in a volume or bind mount outside the container, anything written only inside the container is lost on recreate
  • Never commit a .env file with real secrets to a public repository
  • Avoid the latest tag for anything you rely on, pin a version so an upstream update doesn’t silently change behavior

Troubleshooting

  • Port already in use, another service or the host itself is already bound to that port; change the host-side port mapping
  • Permission denied on bind mounts, the container’s user ID often doesn’t match your host user; check the image’s documented PUID/PGID variables
  • Volume mounted to the wrong path, double-check the container-side path against the image’s documentation, not just the host-side path
  • Container starts but the app fails, check docker compose logs -f before assuming Docker itself is broken
  • latest tag changes behavior unexpectedly, pin to a specific version tag once a stack is stable

Lab Finish Line

A simple service (e.g. Uptime Kuma) deployed through Compose, with data in a bind mount you could back up right now.

What to Build Next

NEXT STEP

Want this running in your business?

Everything in the Lab is a service we deliver. If this guide describes your problem, skip the DIY weekend — send the brief.

FIVE MINUTES TO WRITE · A WRITTEN PLAN BACK · NO SALES CALL UNLESS YOU WANT ONE