Docker Compose YAML

๐Ÿ”ฅ Vibe Prompt

"Create a docker-compose.yml for a web app with FastAPI, Postgres, Redis. Define health checks, volumes, networks."

version: "3.9"

services:
  api:
    build: ./api
    ports: ["8000:8000"]
    depends_on:
      db: { condition: service_healthy }
      redis: { condition: service_started }
    env_file: .env
    volumes: ["./api:/app"]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      retries: 3

  db:
    image: postgres:16-alpine
    volumes: ["pgdata:/var/lib/postgresql/data"]
    environment:
      POSTGRES_DB: myapp
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    healthcheck:
      test: ["CMD", "pg_isready"]
      interval: 10s

  redis:
    image: redis:7-alpine
    volumes: ["redisdata:/data"]

volumes:
  pgdata:
  redisdata:

Key Directives

| Directive | Purpose | |-----------|---------| | depends_on | Service startup order | | healthcheck | Service readiness probe | | volumes | Persistent data (named/bind) | | networks | Service isolation | | env_file | Environment variables | | restart | Restart policy (always/no/on-failure) |

Commands

docker compose up -d          # Start all
docker compose logs -f api    # Follow logs
docker compose exec api bash  # Exec into container
docker compose down -v        # Stop + remove volumes
docker compose restart api    # Restart single service

Chapter Summary

  • Understand core concepts and principles
  • Master implementation methods and techniques
  • Familiar with common issues and solutions
  • Able to apply in real projects

Further Reading

  • Official documentation and API references
  • Open source examples on GitHub
  • Technical books and online courses
  • Community discussions and tech blogs

Implementation Example

Basic Example

# This section provides a complete implementation example

Steps

  1. Setup: Configure development environment
  2. Data: Prepare required data
  3. Implementation: Build core functionality
  4. Testing: Verify correctness
  5. Optimization: Improve performance

Common Errors

| Error Type | Cause | Solution | |------------|-------|----------| | Compilation | Syntax | Check code syntax | | Runtime | Environment | Verify dependencies installed | | Logic | Algorithm | Step-by-step debugging | | Performance | Efficiency | Use profilers |

Code Example

import sys

def main():
    print("Hello, World!")

if __name__ == "__main__":
    main()

References

  • Official documentation
  • API reference
  • Open source examples
  • Community discussions

Docker Compose File Structure

A docker-compose.yml file has three top-level sections:

version: "3.9"  # Compose file format version

services:         # The containers to run
  web:
    image: nginx
    ports:
      - "80:80"

volumes:          # Persistent data storage
  mydata:

networks:         # Communication between services
  mynetwork:

Service Configuration Reference

| Key | Description | Example | |-----|-------------|--------| | image | Container image to use | image: postgres:16-alpine | | build | Build context and Dockerfile | build: . or build: context: ./dir dockerfile: Dockerfile.dev | | ports | Port mappings (HOST:CONTAINER) | ports: "3000:3000" | | environment | Environment variables | environment: NODE_ENV=production | | env_file | Load variables from file | env_file: .env | | volumes | Mount volumes or bind mounts | volumes: ./data:/data | | networks | Attach to networks | networks: frontend | | depends_on | Startup dependencies | depends_on: db | | restart | Restart policy | restart: always | | healthcheck | Container health check | healthcheck: test: ["CMD", "pg_isready"] | | command | Override default command | command: npm start | | entrypoint | Override entrypoint | entrypoint: ["/bin/sh", "-c"] | | user | Run as specific user | user: "1000:1000" | | working_dir | Working directory inside container | working_dir: /app | | container_name | Custom container name | container_name: my-app | | labels | Metadata labels | labels: com.example.version="1.0" | | logging | Log driver configuration | logging: driver: json-file options: max-size: "10m" |

Complete Example: Web App with PostgreSQL

version: "3.9"

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DB_HOST: db
      DB_PORT: 5432
      DB_USER: myapp
      DB_PASSWORD: ${DB_PASSWORD}
      DB_NAME: myapp_prod
    depends_on:
      db:
        condition: service_healthy
    restart: always
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: myapp_prod
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myapp"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  redis:
    image: redis:7-alpine
    restart: always
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

Run Commands

# Start in background
docker compose up -d

# View logs
docker compose logs -f

# View logs for a specific service
docker compose logs -f web

# Execute command in container
docker compose exec web bash

# View running containers
docker compose ps

# Stop and remove
docker compose down

# Stop and remove including volumes
docker compose down -v

# Rebuild and start
docker compose up -d --build

# Restart a specific service
docker compose restart web

Environment Variables (.env)

# .env file (in the same directory as docker-compose.yml)
DB_PASSWORD=your_strong_password_here
NODE_ENV=production
API_KEY=sk-abc123...

Variables are referenced in docker-compose.yml with ${VARIABLE_NAME} syntax.

Best Practices

| Practice | Reason | |----------|--------| | Pin specific image versions | postgres:16-alpine not postgres:latest | | Add health checks to every service | depends_on waits for health, not just startup | | Use .env files for secrets | Never hardcode passwords in compose files | | Use named volumes for databases | Data persists across container restarts | | Configure log rotation | Prevents disks from filling up | | Add restart: always | Containers restart automatically after crashes | | Use multi-stage Dockerfiles | Smaller, more secure production images | | Separate dev and prod compose files | Keep dev overrides separate from production | | Validate with docker compose config | Check for syntax errors before deploying | | Set container_name only when needed | Docker auto-generates unique names by default |

Common Mistakes

| Mistake | Fix | |---------|-----| | Forgetting to add health check | depends_on waits for container start, not readiness | | Hardcoding passwords in YAML | Use ${DB_PASSWORD} with .env file | | Using latest tag | Pin to specific versions for reproducibility | | No restart policy | Container stops after crash and stays down | | No log rotation | Logs grow until disk is full | | Mounting host directories in production | Use named volumes instead of bind mounts | | Exposing database ports to host | Only expose application ports (DB should be internal) | | Putting secrets in docker-compose.yml | Use .env files or Docker secrets |

Summary

Docker Compose simplifies multi-container application management. Define services, volumes, and networks in a YAML file, then start everything with a single command. Add health checks, restart policies, log rotation, and environment variables for production readiness.

Key takeaways:

  • Services: define what containers to run
  • Volumes: persist data beyond container lifetime
  • Networks: control service-to-service communication
  • Health checks: depends_on waits for service readiness
  • .env files: keep secrets out of compose files
  • docker compose up -d: start all services
  • docker compose logs -f: view all logs
  • Pin image versions, never use latest in production

What's Next: Multi-Service Setup

The next chapter covers multi-service Docker Compose setups โ€” coordinating web, API, database, cache, and queue services with proper dependency management.

Member Exclusive Free Tutorial

This chapter is free exclusive content for registered members! Please login or register to unlock immediately.

Login / Register Now