DEV Community

Cover image for Mastering Docker Compose: A Practical Guide for Developers
yukaty
yukaty

Posted on

Mastering Docker Compose: A Practical Guide for Developers

Looking to improve your development workflow with Docker Compose? This guide covers everything developers should know - from basic setup to common troubleshooting patterns.

Table of Contents ๐Ÿ“‹

What is Docker Compose? ๐Ÿ™

Docker Compose makes it easy to run multiple containers together. This is a great tool for local development and testing without messing your machine.

Instead of starting each service (like the database, backend, and frontend) separately, Compose lets you define everything in a single file compose.yml (or docker-compose.yml for older versions) and start them with a single command.

Basic Setup ๐Ÿ“Œ

Docker Compose Template

Hereโ€™s a minimal yet practical template for a backend app and database:

services:
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    environment:
      - DB_HOST=database
      - DB_USER=postgres
      - DB_PASSWORD=secretpassword
    depends_on:
      # Waits for 'database' service to start
      - database
    volumes:
      # Mounts local directory to container for live code updates
      - ./backend:/app

  database:
    image: postgres:17
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secretpassword
    volumes:
      # Persists data using named volume 'db_data'
      - db_data:/var/lib/postgresql/data

volumes:
  # Declares the named volume
  db_data:
Enter fullscreen mode Exit fullscreen mode

Key Features:

  • depends_on: Ensures services start in order.
  • volumes: Supports persistent data and live code updates.
  • Environment variables: Simple configuration for connections.

Configuration Priority

Docker Compose uses this file priority:

1. compose.yml
2. compose.yaml
3. compose.override.yml
4. compose.override.yaml
Enter fullscreen mode Exit fullscreen mode

Note: docker-compose.yml was the standard name for many years. While still valid, Docker now defaults to compose.yml in modern projects. If you are using an older environment or tools, docker-compose.yml will still work seamlessly.

You can use override files for development-specific settings:

# compose.yml (base configuration)
services:
  backend:
    build: ./backend
    environment:
      - NODE_ENV=production

# compose.override.yml (development overrides)
services:
  backend:
    environment:
      - NODE_ENV=development
    volumes:
      - ./backend:/app
Enter fullscreen mode Exit fullscreen mode

Ignore overrides with:

docker compose -f compose.yml up -d
Enter fullscreen mode Exit fullscreen mode

Essential Commands ๐Ÿ’ก

Basic Operations

# Start services
docker compose up -d          # Detached mode
docker compose up --build     # Rebuild images

# Stop services
docker compose stop           # Stops running containers without removing them.
docker compose down           # Stops and removes containers and networks.
Enter fullscreen mode Exit fullscreen mode

Common Tasks

Frequently used commands during development:

# Check running services
docker compose ps

# View service logs for all services
docker compose logs -f

# Restart a single service (for quick iterations)
docker compose restart backend
Enter fullscreen mode Exit fullscreen mode

Cleaning Up Services

Keeping your environment clean is essential. Here are the key commands for managing unused resources and containers:

Command Description
docker compose down -v Stops and removes all containers, networks, and volumes.
docker compose down --remove-orphans Removes unused containers not defined in the compose.yml.
docker compose rm -f [service_name] Forcibly removes specific containers without stopping the project.

Usage:

  • down -v: Use for a complete cleanup, including persistent data and volumes.
  • down --remove-orphans: Ideal for clearing out leftover or unrelated containers.
  • rm -f [service_name]: Quickly remove specific containers.

Building and Starting Services

Hereโ€™s a quick reference for commonly used commands to build images and start containers:

Command Description
docker compose up Starts services defined in compose.yml.
docker compose build Rebuilds service images without starting containers.
docker compose up --build Rebuilds service images and starts services together.

Usage:

  • up: Start containers when images are already built.
  • build: Rebuild images when changes are made to the Dockerfile or dependencies.
  • up --build: Rebuild and start services in one step. Ideal for quick iterations.

Working with Containers

You can interact with containers using Service Names (recommended for docker compose) or Container Names (standalone docker commands):

Using Docker Compose (Service Name)

Service names, defined in compose.yml, make interaction easier:

docker compose exec database bash                      # Access the container shell
docker compose exec database psql -U postgres -d myapp # Connect to the PostgreSQL
Enter fullscreen mode Exit fullscreen mode

Note: Service names are defined in the services section of compose.yml.

Using Docker Commands (Container Name)

Use container names, shown in docker ps, for manual interactions:

docker exec -it myapp-db bash                       # Access the container shell
docker exec -it myapp-db psql -U postgres -d myapp  # Connect to PostgreSQL
Enter fullscreen mode Exit fullscreen mode

Note: Docker automatically generates names (e.g., database_1) unless you manually set container_name. Avoid this for scaling.


Development Workflow ๐Ÿ”„

Use the following commands based on the type of changes:

  • Code Changes: Restart the service.
docker compose restart backend
Enter fullscreen mode Exit fullscreen mode
  • Dockerfile or Dependency Changes: Rebuild and restart.
docker compose up --build backend
Enter fullscreen mode Exit fullscreen mode
  • Full Cleanup and Reset:
docker compose down -v            # Stop and clean up everything
docker compose up --build         # Rebuild and restart all services
Enter fullscreen mode Exit fullscreen mode

Troubleshooting ๐Ÿ› ๏ธ

Port Allocation Errors

When you see an error like this:

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

It means the local port 8000 is already in use.

Solutions:

  1. Check Port Usage: Find the process using the port:
lsof -i :8000
Enter fullscreen mode Exit fullscreen mode
  1. Kill the Process: Terminate the process occupying the port:
kill -9 <PID>
Enter fullscreen mode Exit fullscreen mode
  1. Change the Port: Update compose.yml to use a different local port:
   ports:
      - "8080:8000"  # Map local port 8080 to container port 8000
Enter fullscreen mode Exit fullscreen mode

Advanced Features โšก

Network Configuration

Define custom networks to enable secure communication between services:

services:
  backend:
    networks:
      - app-network

  database:
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Tip: Use docker network ls and docker network inspect to troubleshoot network issues.

Health Checks

Ensure services are ready before other services depend on them:

services:
  database:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
Enter fullscreen mode Exit fullscreen mode
  • Purpose: Prevents dependent services from starting too early.

Resource Management

Control resource usage to ensure stable performance:

services:
  backend:
    deploy:
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
Enter fullscreen mode Exit fullscreen mode
  • Purpose: Avoids a single service consuming too many resources.

Conclusion ๐ŸŽฏ

Docker Compose might look complex at first, but understanding these basics will help you manage most situations.

  • Start simple.
  • Use the right command for the task.
  • Keep your environment clean.

I hope this guide is helpful. Let me know if you have suggestions or spot anything I missed! ๐Ÿ’ฌ

Happy containerizing! ๐Ÿณ

Top comments (0)