Docker Compose — Compose vs Docker Run

2 minute read

This page gives you a side-by-side comparison of running containers with docker run commands versus defining them in a compose.yml file. By the end, you’ll see why Compose is the better approach for anything beyond a single container.


Side-by-Side Comparison

Example: WordPress + MySQL

With docker run (imperative):

# Step 1: Create a network
docker network create wordpress-net

# Step 2: Create a volume
docker volume create wp-db-data

# Step 3: Start MySQL
docker run -d \
  --name wordpress-db \
  --network wordpress-net \
  -e MYSQL_ROOT_PASSWORD=rootpass \
  -e MYSQL_DATABASE=wordpress \
  -e MYSQL_USER=wpuser \
  -e MYSQL_PASSWORD=wppass \
  -v wp-db-data:/var/lib/mysql \
  mysql:8

# Step 4: Start WordPress
docker run -d \
  --name wordpress-app \
  --network wordpress-net \
  -e WORDPRESS_DB_HOST=wordpress-db \
  -e WORDPRESS_DB_USER=wpuser \
  -e WORDPRESS_DB_PASSWORD=wppass \
  -e WORDPRESS_DB_NAME=wordpress \
  -p 8080:80 \
  wordpress:latest

With Docker Compose (declarative):

# compose.yml
services:
  db:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppass
    volumes:
      - db-data:/var/lib/mysql

  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppass
      WORDPRESS_DB_NAME: wordpress
    depends_on:
      - db

volumes:
  db-data:
docker compose up -d

Comparison Table

Aspect docker run Docker Compose
Commands Multiple commands One command (up / down)
Network Must create manually Created automatically
Volumes Must create manually Declared in file
Reproducibility Copy-paste commands Share the YAML file
Version control Hard to track changes Git-friendly YAML
Cleanup Must stop/remove each container docker compose down cleans all
Dependencies Manual ordering depends_on handles it
Scaling Run same command N times --scale web=3
Documentation Commands in a README YAML is self-documenting
Onboarding “Run these 7 commands in order” “Run docker compose up”

What Compose Automates

docker run approach:              Docker Compose approach:
─────────────────────             ─────────────────────
1. Create network       ┐        1. docker compose up
2. Create volume        │           │
3. Start container A    │           ├─ Creates networks ✓
4. Start container B    ├─ Manual   ├─ Creates volumes  ✓
5. Start container C    │           ├─ Starts services  ✓
6. Hope order is right  │           ├─ Handles ordering ✓
7. Debug connection     ┘           └─ Connects DNS     ✓

When docker run is Still Fine

Scenario Why
Quick one-off container docker run -it ubuntu bash — fast and simple
Testing a single image docker run -p 8080:80 nginx — no compose needed
Scripted automation When the script handles orchestration already

The Cleanup Problem

With docker run, cleanup is manual and error-prone:

# Stopping everything — hope you remember all the names
docker stop wordpress-app wordpress-db
docker rm wordpress-app wordpress-db
docker network rm wordpress-net
# Forgot the volume? It's still there, eating disk space

With Compose:

# Everything, gone, clean
docker compose down

# Including volumes
docker compose down -v

Summary

Item Detail
docker run Good for single, quick containers
Docker Compose Good for multi-container applications
Automatic networking Compose creates a default network
Cleanup docker compose down removes everything
Best practice Use Compose for anything with 2+ containers

Quick Reference

Item Detail
docker run Good for single quick containers
Docker Compose Required for multi-container apps
Network creation Automatic in Compose, manual with docker run
Cleanup docker compose down removes everything
Version control compose.yml is Git-friendly
Team sharing Just share the compose.yml file

← When to Use Compose Compose Ecosystem →