

Multi-Environment Docker Compose Setup ¶
- A comprehensive example of structuring Docker Compose files for multiple environments
- Demonstrates environment-specific overrides and configuration management
- Each environment is fully isolated with its own configuration and services
Pre-Requirements ¶
- Docker installed
- Docker Compose knowledge
- Basic understanding of environment variables
- Overview
- Project Structure
- Step 01 - Understanding the Base Configuration
- Step 02 - Development Environment
- Step 03 - Production Environment
- Step 04 - Environment Variables
- Shared Variables (
.env) - Development Variables (
.env.dev) - Production Variables (
.env.prod) - Step 05 - Quick Start with Scripts
- Using the run.sh Script
- Step 06 - Manual Commands
- Start Specific Environment
- Stop Services
- View Logs
- Scale Services (Production)
- Step 07 - Testing the Setup
- Interactive Demo
- Manual Testing
- Step 08 - Clean Up
- Best Practices
- Troubleshooting
- Common Issues
- Debugging Commands
- Environment-Specific Notes
Overview¶
This lab demonstrates how to structure Docker Compose files for multiple environments using:
- Base Configuration: Common services shared across environments
- Environment Overrides: Specific configurations for development and production
- Environment Variables: Centralized configuration management
- Utility Scripts: Easy environment management
Project Structure¶
Labs/006-DockerCompose-env/
├── docker-compose.yml # Base services configuration
├── docker-compose.dev.yml # Development overrides
├── docker-compose.prod.yml # Production overrides
├── .env # Shared environment variables
├── .env.dev # Development-specific variables
├── .env.prod # Production-specific variables
├── README.md # This documentation
├── run.sh # Bash script for environment management
├── demo.sh # Interactive demonstration
├── init.sql # Database initialization
├── html/
│ └── index.html # Sample web application
└── api/
├── package.json # Node.js API dependencies
└── server.js # Sample API server
Step 01 - Understanding the Base Configuration¶
The docker-compose.yml file contains the core service definitions that are common across all environments:
- Web Service: Nginx web server
- API Service: Node.js backend application
- Database Service: PostgreSQL database
- Cache Service: Redis caching layer
All services use environment variables with default values using the ${VARIABLE:-default} syntax for flexibility.
Step 02 - Development Environment¶
The development environment (docker-compose.dev.yml) provides developer-friendly features:
# Start development environment
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml up -d
Development Features:
- Hot reload enabled for API service (nodemon)
- Debug ports exposed (9229 for Node.js debugging)
- Additional development tools:
- Adminer for database management
- MailCatcher for email testing
- Read-write volumes for live code editing
- Detailed logging enabled
- Non-standard ports to avoid conflicts (8000, 3001, 5433, 6380)
Development Services Access:
- Web Application:
http://localhost:8000 - API:
http://localhost:3001 - Database Admin (Adminer):
http://localhost:8080 - Mail Catcher:
http://localhost:1080
Step 03 - Production Environment¶
The production environment (docker-compose.prod.yml) focuses on performance and security:
# Start production environment
docker-compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml up -d
Production Features:
- Multiple service replicas for high availability
- Read-only volumes for security
- Optimized restart policies
- Structured logging with rotation
- Monitoring with Prometheus
- Standard service ports (80, 3000, 5432, 6379)
Production Services Access:
- Web Application:
http://localhost:80 - API:
http://localhost:3000 - Monitoring (Prometheus):
http://localhost:9090
Step 04 - Environment Variables¶
Shared Variables (.env)¶
Common configuration across all environments:
| Variable | Description |
|---|---|
APP_NAME | Application name for container naming |
ENVIRONMENT | Current environment identifier |
DB_NAME | Database name |
DB_USER | Database user |
API_SECRET | API authentication secret |
LOG_LEVEL | Logging verbosity |
Development Variables (.env.dev)¶
| Variable/Setting | Description |
|---|---|
| Non-standard ports | Avoid conflicts with other services |
| Debug-friendly config | Enables debug mode and verbose logging |
| Dev DB credentials | Uses development database credentials |
| Enhanced logging | More detailed logs for debugging |
Production Variables (.env.prod)¶
| Variable/Setting | Description |
|---|---|
| Standard service ports | Uses standard ports for production |
| Strong, secure passwords | Enforces strong credentials |
| Optimized timeouts | Sets timeouts suitable for production |
| Security-focused config | Enables production security best practices |
Step 05 - Quick Start with Scripts¶
Using the run.sh Script¶
# Development environment
./run.sh dev up # Start development
./run.sh dev down # Stop development
./run.sh dev logs # View development logs
./run.sh dev ps # Show service status
# Production environment
./run.sh prod up # Start production
./run.sh prod down # Stop production
./run.sh prod logs # View production logs
# Help
./run.sh help # Show usage information
Step 06 - Manual Commands¶
Start Specific Environment¶
# Development
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml up -d
# Production
docker-compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml up -d
Stop Services¶
# Development
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml down
# Production
docker-compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml down
View Logs¶
# All services logs
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml logs -f
# Specific service logs
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml logs -f api
Scale Services (Production)¶
# Scale API service to 5 replicas
docker-compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml up -d --scale api=5
Step 07 - Testing the Setup¶
Interactive Demo¶
Run the complete demonstration:
The demo will:
- Start development environment
- Test the application
- Switch to production environment
- Show differences between environments
- Clean up
Manual Testing¶
# Start development environment
./run.sh dev up
# Test the API
curl -s http://localhost:3001/health | python3 -m json.tool
# Test the web application
curl -s http://localhost:8000
# Check service status
./run.sh dev ps
Step 08 - Clean Up¶
# Stop current environment
./run.sh dev down # or ./run.sh prod down
# Complete cleanup (removes volumes)
./run.sh dev down && ./run.sh prod down
docker system prune -f
# Or manually
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml down -v
docker-compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml down -v
Best Practices¶
- Environment Separation: Clear separation between dev, staging, and production configurations
- Security: Different secrets and passwords per environment
- Scalability: Production setup with multiple replicas and monitoring
- Development Experience: Hot reload, debugging ports, and development tools
- Configuration Management: Centralized environment variable management
- Volume Management: Read-only volumes in production, read-write in development
- Logging: Environment-appropriate logging levels and rotation
- Networking: Consistent network setup across environments
Troubleshooting¶
Common Issues¶
- Port conflicts: Ensure no other services are using the same ports
- Environment variables: Verify all required variables are set in
.envfiles - Docker daemon: Ensure Docker is running and accessible
Debugging Commands¶
# Check service logs
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml logs service_name
# Check service status
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml ps
# Inspect container
docker inspect container_name
# Execute command in container
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml exec service_name bash
Environment-Specific Notes¶
| Environment/Aspect | Notes |
|---|---|
| Development | Services may take longer to start due to volume mounts |
| Production | Services use restart policies and may auto-restart on failure |
| Networking | All services communicate through Docker networks |

