DEV Community

Alex Spinov
Alex Spinov

Posted on

Docker Compose Has a Free API — Your Entire Stack in One YAML File

Docker Compose is the free multi-container orchestration tool that defines your entire development environment in one YAML file. Run complex stacks with docker compose up.

Why Docker Compose?

  • One commanddocker compose up starts everything
  • Declarative — define services, networks, volumes in YAML
  • Development environment — identical setup for every team member
  • Service discovery — containers find each other by name
  • Hot reload — mount source code for live development
  • Built into Docker — no separate installation since Docker 20.10+

Quick Start

# compose.yaml
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
      - REDIS_URL=redis://cache:6379
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    volumes:
      - ./src:/app/src  # Hot reload

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  cache:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  pgdata:
Enter fullscreen mode Exit fullscreen mode
# Start everything
docker compose up -d

# View logs
docker compose logs -f app

# Stop everything
docker compose down

# Stop and remove volumes (clean slate)
docker compose down -v
Enter fullscreen mode Exit fullscreen mode

Full-Stack Web App

services:
  # Frontend (React/Next.js)
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ./frontend/src:/app/src
      - /app/node_modules
    environment:
      - NEXT_PUBLIC_API_URL=http://localhost:4000

  # Backend API
  api:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    ports:
      - "4000:4000"
    volumes:
      - ./backend/src:/app/src
    environment:
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
      - REDIS_URL=redis://cache:6379
      - JWT_SECRET=super-secret-key
    depends_on:
      db:
        condition: service_healthy

  # Background workers
  worker:
    build: ./backend
    command: node worker.js
    environment:
      - REDIS_URL=redis://cache:6379
      - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
    depends_on:
      - cache
      - db

  # Database
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 5s
      retries: 5

  # Redis cache + queue
  cache:
    image: redis:7-alpine

  # Adminer (database UI)
  adminer:
    image: adminer
    ports:
      - "8080:8080"

volumes:
  pgdata:
Enter fullscreen mode Exit fullscreen mode

Profiles (Dev vs Production)

services:
  app:
    build: .
    ports:
      - "3000:3000"

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret

  # Only starts in dev profile
  adminer:
    image: adminer
    ports:
      - "8080:8080"
    profiles:
      - dev

  # Only starts in debug profile
  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"
      - "8025:8025"
    profiles:
      - dev
      - debug
Enter fullscreen mode Exit fullscreen mode
# Production (no dev tools)
docker compose up -d

# Development (with adminer + mailhog)
docker compose --profile dev up -d
Enter fullscreen mode Exit fullscreen mode

Multi-Stage Builds

# Dockerfile
# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]
Enter fullscreen mode Exit fullscreen mode

Health Checks

services:
  api:
    build: .
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  cache:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3
Enter fullscreen mode Exit fullscreen mode

Networking

services:
  frontend:
    networks:
      - frontend-net

  api:
    networks:
      - frontend-net   # Can talk to frontend
      - backend-net    # Can talk to db

  db:
    networks:
      - backend-net    # Isolated from frontend

networks:
  frontend-net:
  backend-net:
Enter fullscreen mode Exit fullscreen mode

Docker Compose vs Kubernetes vs Docker Swarm

Feature Docker Compose Kubernetes Docker Swarm
Complexity Low Very High Medium
Best for Dev/small prod Large production Medium production
Scaling Manual Auto-scaling Manual
Config YAML (simple) YAML (complex) YAML
Load balancing Nginx/Traefik Built-in Built-in
Health checks Yes Yes Yes
Secrets Environment/files Secrets API Secrets API

Need to scrape data from any website and get it in structured JSON? Check out my web scraping tools on Apify — no coding required, results in minutes.

Have a custom data extraction project? Email me at spinov001@gmail.com — I build tailored scraping solutions for businesses.

Top comments (0)