If you've read almost any self-hosting guide, including our own home server basics guide, you've run into the word "Docker" — usually with a promise that it makes installing apps easier, and rarely with an explanation of what it actually is. This guide fills that gap: what Docker does, why it exists, and how to read your first Docker Compose file.
The problem Docker solves
Every app needs specific supporting software to run — a particular programming language runtime, specific library versions, particular configuration files. Installing an app the traditional way means installing all of that manually on your actual operating system, and it's easy for one app's requirements to conflict with another's, or with what your OS already has installed. This used to be called "dependency hell," and it's exactly the kind of problem that scared beginners away from self-hosting.
Docker solves this by packaging an app together with everything it needs into one self-contained unit that runs the same way on any machine, isolated from everything else on your system. You don't install the app's dependencies yourself — they're already inside the package.
Images vs. containers
These two terms get used interchangeably by beginners, but they mean different things:
| Term | What it actually is |
|---|---|
| Image | A read-only template — a frozen snapshot of an app plus everything it needs. You download an image once from a registry like Docker Hub. |
| Container | A running instance of an image — the live, working copy actually doing something. You can start, stop, or delete a container without touching the image it came from. |
Think of an image like an app installer file, and a container like the actual running app — except containers start in seconds and can be thrown away and recreated instantly without losing your data, as long as that data lives outside the container itself (more on that below).
Why nearly every self-hosted app uses Docker
- Consistent installs. The instructions "run this file" work the same on nearly any machine, instead of a long list of OS-specific manual steps.
- Isolation. Each app runs in its own bubble, so two apps that need conflicting software versions can run side by side without interfering with each other.
- Easy updates and removal. Updating usually means pulling a newer image and recreating the container; removing an app means deleting its container, with no leftover files scattered across your system.
- Portability. The same Docker setup works whether you're running it on Proxmox, TrueNAS, Unraid, or plain Ubuntu — see our server OS comparison for how each one supports Docker.
Docker Compose: describing your setup in one file
Running one container is easy; running several apps that need to work together gets messy with individual commands. Docker Compose solves this with a single text file (usually named docker-compose.yml) that describes exactly what to run and how — so setting up an app becomes "paste this file, run one command" instead of a long manual walkthrough. Here's a simplified real example for Jellyfin, the media server we cover in our Jellyfin vs Plex guide:
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
ports:
- "8096:8096"
volumes:
- ./config:/config
- ./media:/media
restart: unless-stopped
Reading it line by line:
image— which app to download and run (Jellyfin, in this case).ports— maps a port on your server to a port inside the container, so you can reach Jellyfin's web interface from your browser.volumes— connects folders on your actual hard drive to folders inside the container, so your configuration and media survive even if the container is deleted and recreated.restart: unless-stopped— tells Docker to automatically restart this app after a reboot or crash, so you don't have to manually start it again.
Where do you actually run Docker?
| Platform | How Docker fits in |
|---|---|
| Proxmox VE | Runs inside a VM or LXC container on top of Proxmox — typically a small Ubuntu VM with Docker installed on it. |
| TrueNAS Scale | Built in — the "Apps" section is Docker-based under the hood, with a graphical install flow. |
| Unraid | Built in — the Docker tab and its app store (Community Applications) are widely considered the easiest GUI-based Docker experience. |
| Plain Ubuntu Server | Installed manually — the most control and the most manual setup, favored by more experienced self-hosters. |
None of these are wrong choices — see our full OS comparison for help picking one based on how hands-on you want to be.
Common beginner questions
What happens when I reboot my server? With restart: unless-stopped set (as in the example above), containers start themselves back up automatically — you don't need to relaunch anything by hand.
How do I update an app? You pull the newer version of the image and recreate the container from it. Because your actual data lives in the mapped volumes, not inside the container, updating doesn't touch your files or settings.
What if I break something? Since containers are disposable, the usual fix is simply deleting and recreating the container from the same Compose file — your data in the volumes is untouched, and you're back to a clean working state in seconds.