Blog
3 min read

Docker vs Docker Compose: What's the Difference?

Docker runs individual containers; Docker Compose describes and runs a group of containers that work together — your app, its database and a cache — from one YAML file. How they relate, the same setup with and without Compose, and the commands you'll use.

Docker runs containers. Docker Compose is a tool for running several containers together, described in one file. They aren't alternatives — Compose uses Docker. (What is Docker?)

With plain Docker

Running a web app with a Postgres database using only docker commands:

docker network create myapp

docker run -d --name db --network myapp \
  -e POSTGRES_PASSWORD=secret \
  -v pgdata:/var/lib/postgresql/data \
  postgres:18

docker run -d --name web --network myapp \
  -p 3000:3000 \
  -e DATABASE_URL=postgresql://postgres:secret@db:5432/postgres \
  myapp:latest

It works, but you have to remember all those flags, run them in the right order, and type them again every time.

With Docker Compose

The same setup, written down once in docker-compose.yml (or compose.yaml):

services:
  db:
    image: postgres:18
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://postgres:secret@db:5432/postgres
    depends_on:
      - db

volumes:
  pgdata:

Then:

docker compose up -d

Both containers start, on a shared network, where web can reach the database at the hostname db. (Docker Compose for local development, What is YAML?)

Side by side

Docker Docker Compose
Manages One container per command A group of related containers
Configuration Command-line flags A YAML file in your project
Networking Create networks yourself Automatic shared network
Start everything Several commands docker compose up
Repeatable / shareable Hard Commit the file, anyone runs it

The commands you'll use

docker compose up -d          # start everything in the background
docker compose up -d --build  # rebuild images first
docker compose ps             # what's running
docker compose logs -f web    # follow one service's logs
docker compose exec db psql -U postgres   # run a command inside a service
docker compose restart web
docker compose down           # stop and remove containers (keeps volumes)
docker compose down -v        # also delete volumes — ⚠ deletes database data

(Docker commands cheat sheet)

"docker-compose" vs "docker compose"

The original was a separate Python program, docker-compose (with a hyphen). It was replaced by Compose v2, built into Docker as docker compose (with a space). Use the space version; the old one is no longer maintained. The YAML format is the same.

When to use which

  • One container, quick test: docker run.
  • Anything with more than one piece — app + database, app + worker + Redis: Compose.
  • Local development: Compose is the standard way to get a project's services running with one command.
  • Small production deployments on a single server: Compose works well. (Do you need Kubernetes?)
  • Many servers, auto-scaling, self-healing across machines: that's orchestration territory (Kubernetes, Swarm, Nomad).

Common mistakes

  • Using localhost between containers. Inside a container, localhost is the container itself. Use the service name (db). (ECONNREFUSED explained)
  • depends_on doesn't wait for "ready". It starts the database first but doesn't wait until it accepts connections. Add a healthcheck with condition: service_healthy, or retry in your app.
  • Secrets in the YAML committed to Git. Use an .env file (git-ignored) that Compose reads automatically. (Environment variables)
  • down -v by accident, wiping the database.

EasySpawn runs your app's services together on a server with persistent storage and backups, so you get the convenience of Compose without the server admin. See how it works or join the waitlist.

Related: What Is Docker? · Docker Compose for Local Development · Dockerfile Explained · Docker Volumes vs Bind Mounts

Keep reading