← Back to Home
🐳

Multi-Container Apps with Docker Compose

Define and run your whole stack from one file, with one command.

⏱10 min readπŸ“šDevOps Fundamentals

Real applications aren’t one container β€” they’re an app plus a database, maybe a cache, maybe a queue. Starting each by hand with long docker run commands is error-prone. Docker Compose lets you describe the whole stack in one YAML file and start it all with a single command.


🎯 Learning Objectives

By the end of this lesson you will:


Why Compose?

Without Compose, launching an app + database means several long commands, a shared network, and correct startup order β€” every single time. Compose captures all of that in a file you can version-control and share.

πŸ’‘ The one-line version

Compose is a recipe for your whole application: every service, its config, and how they connect β€” reproducible with one command.


A Compose File, Explained

Here’s a typical stack: a web app talking to a PostgreSQL database.

yaml
services:
web:
  build: .                 # build from the local Dockerfile
  ports:
    - "3000:3000"
  environment:
    DATABASE_URL: postgres://user:pass@db:5432/app
  depends_on:
    - db

db:
  image: postgres:16
  environment:
    POSTGRES_USER: user
    POSTGRES_PASSWORD: pass
    POSTGRES_DB: app
  volumes:
    - pgdata:/var/lib/postgresql/data

volumes:
pgdata:

Key ideas:

⚠ Never commit real secrets

The passwords above are fine for a local demo, but never put real credentials in a committed Compose file. Use a .env file (git-ignored) or a secrets manager for anything real.


Running the Stack

Command What it does
docker compose up -d Build and start all services (detached)
docker compose ps List the stack’s containers
docker compose logs -f Follow logs from all services
docker compose down Stop and remove everything
docker compose down -v …and delete the volumes too
bash β€” 80Γ—24
student@devops:~$docker compose up -d

One command brought up a private network, the database, and the web app in the right order.


Service Discovery by Name

This is the part that trips up beginners: inside a Compose network, you connect to another service by its service name, not localhost.

bash
# Correct β€” 'db' is the service name
DATABASE_URL=postgres://user:pass@db:5432/app

# Wrong β€” localhost points at the app's own container
DATABASE_URL=postgres://user:pass@localhost:5432/app

πŸ’‘ Remember

Each container has its own localhost. To reach another container, use its service name as the hostname.


πŸ§ͺ Hands-on Lab

πŸ“

Stand Up an App + Redis Stack

  1. Write a docker-compose.yml with a web service (nginx) and a cache service (redis)
  2. Start the stack in detached mode
  3. Confirm both containers are running, then tear it all down

🧠 Knowledge Check

Knowledge Check

Inside a Docker Compose network, how does the web service connect to a database service named 'db'?

Knowledge Check

Which command stops the stack AND deletes its named volumes?


πŸ’Ό Interview Preparation

Interview Q&A

When would you use Docker Compose, and when would you reach for Kubernetes instead?


Summary

You’ve completed the Docker track: containers, images, everyday commands, writing Dockerfiles, and orchestrating multi-container stacks with Compose. You can now package and run whole applications reproducibly. Next, we scale up to running containers across a cluster with Kubernetes.

Up Next

Introduction to Kubernetes

You've mastered this lesson. Continue your journey to becoming a DevOps Engineer.

Start Next Lesson→