DEV Community

Michelle
Michelle

Posted on

30-Day Cloud & DevOps Challenge: Day 7 — Docker Compose: One Command to Rule Them All

Yesterday, I had two containers: one for my backend, one for my frontend.

But running them meant two terminals, two docker run commands, and remembering which port mapped to what.

Today, I fixed that forever.

I learned Docker Compose a tool that lets me define my entire application stack in one file and start everything with a SINGLE command.


First: What Problem Does Docker Compose Solve?

Without Docker Compose (Days 5 & 6)

# Terminal 1
cd backend
sudo docker build -t backend-app .
sudo docker run -p 3001:5000 backend-app

# Terminal 2 (new terminal)
cd frontend
npm run build
sudo docker build -t frontend-app .
sudo docker run -p 8080:80 frontend-app
Enter fullscreen mode Exit fullscreen mode

The pain:

  • Multiple terminals
  • Many commands to remember
  • Containers don't automatically know about each other
  • Hard to share setup with others

With Docker Compose (Today)

# One terminal. One command.
sudo docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

That's it. Everything runs.


What is Docker Compose?

In one sentence: Docker Compose is a tool that lets you define and run multiple Docker containers together using a single YAML file.

The Analogy

Concept Docker Alone Docker Compose
Individual containers Shipping containers Shipping containers
Managing them Moving each by hand A crane operator with a manifest
Documentation Remember what goes where Everything in one file

Docker Compose is the crane operator + manifest that organizes all your containers at once.


Step 1: Creating docker-compose.yml

First, I went to my project root:

cd ~/Desktop/Production-Ready-Microservices-Platform
Enter fullscreen mode Exit fullscreen mode

Then I created the Compose file:

touch docker-compose.yml
nano docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

Step 2: Writing the Compose File (Line by Line)

Line 1: Version

version: '3.8'
Enter fullscreen mode Exit fullscreen mode

What this means: Which version of Docker Compose syntax to use (3.8 is current).

Line 2: Services Section

services:
Enter fullscreen mode Exit fullscreen mode

What this means: Everything below defines containers (called "services").

Lines 3-6: Backend Service

  backend:
    build: ./backend
    ports:
      - "3001:5000"
Enter fullscreen mode Exit fullscreen mode
Line Meaning
backend: Name of the service
build: ./backend Build image using Dockerfile in ./backend
ports: Define port mapping
- "3001:5000" Map host 3001 → container 5000

Lines 7-10: Frontend Service

  frontend:
    build: ./frontend
    ports:
      - "8080:80"
Enter fullscreen mode Exit fullscreen mode

Same pattern, but for the frontend (port 8080 → 80).

The Complete File

version: '3.8'

services:
  backend:
    build: ./backend
    ports:
      - "3001:5000"

  frontend:
    build: ./frontend
    ports:
      - "8080:80"
Enter fullscreen mode Exit fullscreen mode

That's it! 12 lines to define my entire application.


Step 3: What Docker Compose Does Behind the Scenes

When I ran docker-compose up --build, Compose did ALL of this automatically:

# 1. Created a shared network
docker network create microservices-platform_default

# 2. Built backend image
docker build -t microservices-platform-backend ./backend

# 3. Built frontend image
docker build -t microservices-platform-frontend ./frontend

# 4. Started backend container
docker run -d \
  --name microservices-platform-backend-1 \
  --network microservices-platform_default \
  -p 3001:5000 \
  microservices-platform-backend

# 5. Started frontend container
docker run -d \
  --name microservices-platform-frontend-1 \
  --network microservices-platform_default \
  -p 8080:80 \
  microservices-platform-frontend
Enter fullscreen mode Exit fullscreen mode

All of that from one command. That's the magic of Docker Compose.


Step 4: Running Everything

sudo docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

What I saw:

[+] Building 2.5s (15/15) FINISHED
[+] Running 3/3
 ✔ backend   Built
 ✔ frontend  Built
 ✔ Network microservices-platform_default  Created
Enter fullscreen mode Exit fullscreen mode

Then the containers started:

frontend-1  | /docker-entrypoint.sh: Configuration complete; ready for start up
backend-1   | Server is running on http://localhost:5000
backend-1   | Try these endpoints:
backend-1   |   - http://localhost:5000/
backend-1   |   - http://localhost:5000/health
backend-1   |   - http://localhost:5000/users
Enter fullscreen mode Exit fullscreen mode

Both containers running simultaneously in ONE terminal!


Step 5: Testing Everything

Testing the Backend

In a new terminal:

curl http://localhost:3001/health
Enter fullscreen mode Exit fullscreen mode

Response:

{"status":"healthy","service":"backend-api","timestamp":"2026-04-12T13:10:49.057Z"}
Enter fullscreen mode Exit fullscreen mode

Testing the Frontend

In my browser: http://localhost:8080

My React app appeared! Same as Day 3, but now running inside a container managed by Compose.


Step 6: Stopping Everything

To stop all containers:

# In the Compose terminal, press Ctrl+C
Ctrl+C

# Then clean up
sudo docker-compose down
Enter fullscreen mode Exit fullscreen mode

One command stops EVERYTHING. No more hunting for container IDs.


Docker vs Docker Compose: The Comparison

Task Docker Alone Docker Compose
Run one container docker run ... Overkill
Run multiple containers Multiple commands docker-compose up
Connect containers Manual network setup Automatic network
Start order Manual (wait, then start) depends_on
Environment variables -e flag each time In file
Port mapping -p flag each time In file
Share setup Send commands to friend Send one file
Rebuild after changes Manual rebuild --build flag
View logs docker logs ID docker-compose logs

Why Your Project NEEDS Docker Compose

Your Architecture

User → Frontend (React) → Backend (Node.js) → (Soon: PostgreSQL)
Enter fullscreen mode Exit fullscreen mode

Each component has different needs:

Need Frontend Backend Database (coming)
Base image nginx:alpine node:18-alpine postgres:15
Port 80 5000 5432
Storage None None Persistent volume
Start order Last Middle First
Scale for User traffic API calls Data growth

Without Compose (Manual Nightmare)

# Start database
docker run -d --name postgres -v postgres_data:/var/lib/postgresql/data postgres:15

# Wait for database
sleep 5

# Start backend
docker run -d --name backend --link postgres -e DB_HOST=postgres backend-app

# Start frontend
docker run -d --name frontend -p 8080:80 frontend-app

# Create network
docker network create myapp
docker network connect myapp postgres backend frontend

# To stop: 4 separate commands
Enter fullscreen mode Exit fullscreen mode

15+ commands! One mistake and nothing works.

With Compose (One File)

version: '3.8'

services:
  postgres:
    image: postgres:15
    volumes:
      - postgres_data:/var/lib/postgresql/data

  backend:
    build: ./backend
    depends_on:
      - postgres
    environment:
      - DB_HOST=postgres

  frontend:
    build: ./frontend
Enter fullscreen mode Exit fullscreen mode
# ONE command
docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

3 commands total. Perfect every time.


Issues I Ran Into

Issue 1: "no configuration file provided"

Error:

no configuration file provided: not found
Enter fullscreen mode Exit fullscreen mode

Cause: I was in the wrong directory.

Fix:

cd ~/Desktop/Production-Ready-Microservices-Platform
ls -la docker-compose.yml  # Verify file exists
Enter fullscreen mode Exit fullscreen mode

Issue 2: Port already allocated

Error:

Bind for 0.0.0.0:8080 failed: port is already allocated
Enter fullscreen mode Exit fullscreen mode

Cause: I still had my old frontend container running from Day 6.

Fix:

sudo docker ps  # Find running containers
sudo docker stop <container_id>  # Stop the old one
sudo docker-compose up  # Now it works
Enter fullscreen mode Exit fullscreen mode

Issue 3: The "version is obsolete" warning

Warning:

the attribute `version` is obsolete, it will be ignored
Enter fullscreen mode Exit fullscreen mode

Fix: I can remove the version: '3.8' line — newer Docker versions don't need it.


Docker Compose Commands Cheat Sheet

Command What it does
docker-compose up Start all services
docker-compose up -d Start in background (detached)
docker-compose up --build Rebuild images then start
docker-compose down Stop and remove containers
docker-compose down -v Also remove volumes (databases!)
docker-compose ps Show status of services
docker-compose logs View logs from all services
docker-compose logs backend View logs from backend only
docker-compose build Rebuild images without starting
docker-compose restart Restart all services

Key Takeaways

  1. Docker Compose = Multiple containers, one command — No more terminal juggling
  2. Everything in one file — Share your setup with anyone
  3. Automatic networking — Containers can find each other by name
  4. Declarative configuration — Say WHAT you want, not HOW
  5. Local = Production — Same Compose file works everywhere

Resources

Top comments (0)