Spin up a self-hosted app the manual way and you are juggling container flags, port mappings and volume mounts across a dozen long terminal commands you will never remember. Docker Compose basics replace all of that with one readable file: you describe the whole stack in docker-compose.yml, then bring it online with a single docker compose up -d. Reproducible, version-controlled and trivial to move to another machine.

Quick Answer

Docker Compose defines a multi-container application in one YAML file (docker-compose.yml) and starts the entire stack with docker compose up -d. You describe each service, its persistent volumes and the networks that connect them once, then commit that file to git so the same setup runs identically on any host.

What Compose is solving

A real self-hosted app is rarely one container. A typical stack might be an app server, a PostgreSQL database, a cache and a reverse proxy. Wiring those together by hand with individual docker run commands is fragile and undocumented. Compose lets you declare the whole stack in a single file and manage its services, networks and volumes together, which is why it has become the common language of self-hosted infrastructure for the likes of Nextcloud, Jellyfin and Vaultwarden.

The three building blocks

Every Compose file is built from three concepts, and understanding them is most of the battle.

Services

A service is one container your application needs, such as a web app, a database or a proxy. Each service entry names the image to run, the ports to publish, the environment variables to pass and which networks and volumes it attaches to. You can define several services in one file and Compose starts them together.

Volumes

Containers are disposable; their internal storage vanishes when they are recreated. Volumes provide persistent storage that survives restarts and upgrades, so your database files, uploads and configuration live on even when you pull a newer image. Naming a volume and mounting it into a service is how you keep data safe across rebuilds.

Networks

Networks control which containers can talk to each other. The practical pattern is to separate by trust level: put public-facing services such as a reverse proxy on one network, and keep database and cache containers on an internal-only network so they are unreachable from the outside even if the app layer is compromised.

A minimal example walkthrough

A simple two-service stack looks like this in plain terms: one service block for the app (publishing a port and depending on the database), one service block for PostgreSQL (with environment variables for its credentials and a named volume for its data), and one internal network the two share. Save it as docker-compose.yml in a folder, drop into that folder in your terminal, and the whole thing is one command away.

The key commands you will use day to day:

  1. docker compose up -d brings the stack online in the background.
  2. docker compose ps shows what is running.
  3. docker compose logs -f follows the output to debug a problem.
  4. docker compose down stops and removes the containers (your named volumes stay).
  5. docker compose pull then up -d upgrades to newer images.

Where to run it

Compose runs anywhere Docker does, but a self-hosted stack you want online around the clock belongs on an always-on, low-power machine rather than your daily desktop. A small fanless box sitting in a cupboard is ideal, and the compact mini PCs in the Evetech range suit this perfectly: enough cores and memory to run several containers, low enough draw to leave on permanently. If you would rather one machine do double duty as both workstation and host, comparing it against the Evetech PC best sellers gives you a sense of the headroom a fuller system buys.

Back up the docker-compose.yml file and your volume data, and migrating the entire stack to new hardware is little more than copying two things across and running up again.

Frequently Asked Questions

What is the difference between docker run and Docker Compose?

A docker run command starts one container with all its options typed inline. Compose describes one or many containers, plus their volumes and networks, in a single file you can re-run, edit and commit to git. For anything beyond a single throwaway container, Compose is far easier to maintain.

Does docker compose up -d delete my data?

No. The -d flag simply runs the stack in the background. Your data persists as long as it lives in named volumes, which survive docker compose down. Data is only lost if you explicitly remove the volumes with the -v flag.

Why split services across separate networks?

To limit exposure. Putting databases and caches on an internal-only network means they cannot be reached from outside even if your public-facing service is breached. Only the services that need to face the internet sit on the external network.

Can one Compose file run several different apps?

It can, but the cleaner approach is one folder and one docker-compose.yml per app. That keeps each stack independently startable, upgradeable and backable up without disturbing the others.

How do I move my whole stack to a new machine?

Copy the docker-compose.yml file and the contents of your named volumes to the new host, install Docker, then run docker compose up -d in the same folder. Because the configuration is fully described in the file, the stack comes up identically.

Planning an always-on home server? Browse the low-power mini PCs at Evetech that are ideal for running a Docker Compose stack quietly in the background, day and night.