CloudOpsGuide
docker

Docker Compose Tutorial: From Zero to Multi-Container Apps

Beginner
10 minutes
October 2026
CloudOpsGuide Team

Docker Compose Tutorial: From Zero to Multi-Container Apps

Docker Compose takes you from docker run incantations to describing a whole application stack in one YAML file. This tutorial goes from zero to running a multi-container app with networking, volumes, and environments.

Table of Contents

Install Compose

Compose v2 ships as a Docker plugin — no separate install on Docker Desktop. On Linux servers:

docker compose version    # should print v2.x
# if missing, on Debian/Ubuntu:
sudo apt-get install docker-compose-plugin

Your first compose file

Create compose.yaml (or the legacy docker-compose.yml):

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"
docker compose up -d       # start in background
docker compose ps          # what's running
docker compose logs -f     # stream logs
docker compose down        # stop and remove containers

A real stack: app + database + cache

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://app:secret@db:5432/appdb
      REDIS_URL: redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: appdb
    volumes:
      - dbdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 3s
      retries: 10

  cache:
    image: redis:7-alpine

volumes:
  dbdata:

Key concepts, explained fast

  • Services = containers, defined declaratively. Each service gets a DNS name matching its key — db, cache — which is how app finds them.
  • Networks — Compose creates a private network per project; services reach each other by name, nothing is exposed to the internet unless you publish a port.
  • Volumes — named volumes persist data across down/up. Anonymous container storage does not.
  • depends_on + healthcheck — controls start order; healthy conditions prevent race conditions like the app crashing before Postgres is ready.
  • build: . — builds a local Dockerfile; combine with image: to name the result.

Daily-driver commands

docker compose up -d --build     # rebuild changed images
docker compose exec db psql -U app appdb   # shell into a service
docker compose restart app       # restart one service
docker compose logs -f --tail=50 app
docker compose down -v           # also delete volumes (careful!)

Override files for environments

Compose merges compose.yaml with compose.override.yaml automatically — keep dev tweaks there. For prod, use docker compose -f compose.yaml -f compose.prod.yaml up -d to layer explicit overrides.

Where to go next

When one file isn't enough: profiles (profiles: [debug]), secrets via secrets:, resource limits, and eventually our guide on running Compose in production. Compose scales to a surprisingly capable single-host platform before you ever need an orchestrator.

Related Articles


Last Updated: October 2026 Author: CloudOpsGuide Team Difficulty: Beginner Estimated Reading Time: 10 minutes