Skip to content
Plurafy

Docker Compose

Docker Compose orchestrates multi-container applications. Learn to define and manage complex application stacks with Docker Compose.

Define and manage a complete multi-service application stack using Docker Compose with proper networking, volumes, and orchestration.

  • Services: Individual containers
  • Networks: Container communication
  • Volumes: Data persistence
  • Environments: Configuration
  • Dependencies: Service ordering
  • Simple YAML Syntax: Easy configuration
  • Local Development: Full-stack locally
  • Networking: Automatic service discovery
  • Volume Management: Data persistence
  • Environment Management: Configuration
docker-compose.yml
version: '3.9'
services:
# Node.js Application
app:
build:
context: .
dockerfile: Dockerfile
container_name: nodejs-app
ports:
- "3000:3000"
environment:
NODE_ENV: development
DATABASE_URL: postgresql://user:password@db:5432/appdb
REDIS_URL: redis://cache:6379
ELASTICSEARCH_URL: http://search:9200
RABBITMQ_URL: amqp://guest:guest@queue:5672
depends_on:
db:
condition: service_healthy
cache:
condition: service_healthy
search:
condition: service_healthy
queue:
condition: service_healthy
volumes:
- ./src:/app/src
- ./logs:/app/logs
networks:
- app-network
restart: unless-stopped
# PostgreSQL Database
db:
image: postgres:15-alpine
container_name: postgres-db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: appdb
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d appdb"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
# Redis Cache
cache:
image: redis:7-alpine
container_name: redis-cache
command: redis-server --appendonly yes
volumes:
- redis_data:/data
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
# Elasticsearch
search:
image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0
container_name: elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
# RabbitMQ Message Queue
queue:
image: rabbitmq:3-management
container_name: rabbitmq
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
volumes:
- rabbitmq_data:/var/lib/rabbitmq
ports:
- "5672:5672"
- "15672:15672"
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
# Nginx Reverse Proxy
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
networks:
- app-network
volumes:
postgres_data:
redis_data:
elasticsearch_data:
rabbitmq_data:
networks:
app-network:
driver: bridge
# docker-compose.override.yml (Development)
version: '3.9'
services:
app:
build:
context: .
args:
- ENV=development
environment:
DEBUG: "true"
volumes:
- ./src:/app/src
- /app/node_modules
command: npm run dev
db:
environment:
POSTGRES_PASSWORD: devpassword
ports:
- "5432:5432"
---
# docker-compose.prod.yml (Production)
version: '3.9'
services:
app:
build:
context: .
args:
- ENV=production
environment:
NODE_ENV: production
DEBUG: "false"
restart: always
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
db:
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
scripts/compose-manage.sh
#!/bin/bash
set -e
COMPOSE_FILE=${COMPOSE_FILE:-docker-compose.yml}
ENV=${ENV:-development}
function build() {
echo "Building services..."
docker-compose -f $COMPOSE_FILE build
}
function up() {
echo "Starting services..."
docker-compose -f $COMPOSE_FILE up -d
echo "Services are running"
}
function down() {
echo "Stopping services..."
docker-compose -f $COMPOSE_FILE down
echo "Services stopped"
}
function logs() {
echo "Showing logs..."
docker-compose -f $COMPOSE_FILE logs -f
}
function ps() {
echo "Service status:"
docker-compose -f $COMPOSE_FILE ps
}
function migrate() {
echo "Running database migrations..."
docker-compose -f $COMPOSE_FILE exec app npm run migrate
}
function health() {
echo "Checking service health..."
services=$(docker-compose -f $COMPOSE_FILE config --services)
for service in $services; do
if docker-compose -f $COMPOSE_FILE ps $service | grep -q "Up"; then
echo "✓ $service is running"
else
echo "✗ $service is not running"
fi
done
}
case $1 in
build)
build
;;
up)
build && up && migrate && health
;;
down)
down
;;
logs)
logs
;;
ps)
ps
;;
migrate)
migrate
;;
health)
health
;;
restart)
down && up
;;
*)
echo "Usage: $0 {build|up|down|logs|ps|migrate|health|restart}"
exit 1
;;
esac
docker-compose.dev.yml
version: '3.9'
services:
app:
build:
context: .
target: development
environment:
NODE_ENV: development
DEBUG: "true"
volumes:
- ./src:/app/src
- ./tests:/app/tests
- /app/node_modules
ports:
- "3000:3000"
- "9229:9229" # Debugger
command: npm run dev
db:
environment:
POSTGRES_PASSWORD: devpassword
volumes:
- postgres_data:/var/lib/postgresql/data
# Development tools
adminer:
image: adminer
ports:
- "8080:8080"
depends_on:
- db
redis-commander:
image: rediscommander/redis-commander:latest
environment:
- REDIS_HOSTS=local:cache:6379
ports:
- "8081:8081"
depends_on:
- cache
volumes:
postgres_data:
version: '3.9'
services:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
cache:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
# Monitoring with Prometheus
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
# Visualization with Grafana
grafana:
image: grafana/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
  1. Service Definition

    • One service per container
    • Clear naming conventions
    • Document dependencies
    • Set resource limits
  2. Networking

    • Define custom networks
    • Use service names for discovery
    • Expose only needed ports
    • Secure communication
  3. Volumes

    • Named volumes for data
    • Bind mounts for development
    • Proper permissions
    • Backup strategy
  4. Configuration

    • Environment variables
    • Separate dev/prod configs
    • Secrets management
    • Documentation
  5. Operations

    • Health checks
    • Restart policies
    • Logging
    • Monitoring
  • Local Development: Full-stack locally
  • CI/CD Testing: Consistent test environment
  • Demo Environments: Pre-configured demos
  • Microservices: Local service topology
  • Training: Reproducible setups