Docker
The path: 1. Foundation → 2. Tailscale → 3. Docker → 4. Immich
Nobody installs Immich, Jellyfin, or FreshRSS "onto" a server anymore. Everything ships as a container: the app plus everything it needs to run, sealed in a box you can delete and re-create in seconds. Your data lives outside the box in plain folders. Container dies, updates, gets replaced — the data doesn't care.
If you arrived here from Path A or B, install this now. If you're on an LXC, go back and read why that's the wrong foundation for this guide.
Install Docker
On Ubuntu or Debian:
curl -fsSL https://get.docker.com | sh
docker run hello-world
The compose file is the whole religion
Every app ships a docker-compose.yml: a short file declaring what to run, which ports, and which folders hold the data. Your entire job as a self-hoster is maintaining a folder of these. You'll be doing it in nano over SSH, so keep the Terminal Tips warm.
Directory doctrine — pick one home and never deviate:
mkdir -p /opt/stacks
One subfolder per app — /opt/stacks/immich, /opt/stacks/jellyfin — forever. Five years from now, "where's the config for X" has one answer. My own first ride on this particular rodeo was mempool.space in Docker; the pattern you're learning now is the same one.
Rules I enforce on my own lab, earned the hard way:
- Never write a
version:key in compose files. It's obsolete and some tooling errors on it. restart: unless-stoppedon every service, so a power outage self-heals.- Apps on a rolling tag, databases pinned to a major version. A surprise in an app is a bad afternoon; a surprise in a database is data loss.
- Update one stack at a time:
docker compose pull && docker compose up -d, look at it, then touch the next.
Dockge: your cockpit
Dockge is a single web UI for managing compose stacks — the friendly layer between you and a folder of YAML files.
mkdir -p /opt/stacks/dockge && cd /opt/stacks/dockge
nano compose.yaml:
services:
dockge:
image: louislam/dockge:1
restart: unless-stopped
ports:
- "5001:5001"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- /opt/stacks:/opt/stacks
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
docker compose up -d
Browse to http://server-ip:5001 (or your Tailscale hostname) and create your account. From now on you can write, edit, start, stop, and update stacks from a browser — but underneath they're still just folders and files, which means they back up with rsync and restore with docker compose up -d. That symmetry is the entire point.
The vocabulary, once
- Image — the sealed app box, pulled from a registry.
- Container — a running copy of an image. Disposable. Kill it freely.
- Volume / bind mount — the doorway between the container and a real folder on your disk. This is where your data lives. This is what you back up.
That's all the theory. Go get your photos: Immich.