The Importance of Development Environments
To eliminate the "it works on my machine..." problem, all developers need to work in the same environment.
When environments differ
- Build failures due to Node.js version differences
- Query errors due to DB version differences
- Path issues due to OS differences
When environments match
- New team members can start developing right away
- Easy to reproduce bugs
- Same environment as CI/CD
Using docker-compose
docker-compose is a tool for managing multiple containers at once. You can define frontend, backend, and database all in one place.
Basic Setup
services:
# Frontend (React)
frontend:
build: ./frontend
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
environment:
- VITE_API_URL=http://localhost:8080
# Backend (FastAPI)
backend:
build: ./backend
ports:
- "8080:8080"
volumes:
- ./backend:/app
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
depends_on:
- db
# Database (PostgreSQL)
db:
image: postgres:15
ports:
- "5432:5432"
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=myapp
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:Common Commands
# Start all services
docker-compose up
# Start in background
docker-compose up -d
# Restart a specific service
docker-compose restart backend
# View logs
docker-compose logs -f backend
# Stop and remove all services
docker-compose down
# Remove volumes as well (caution!)
docker-compose down -vHot Reload Setup
Mount volumes so code changes are reflected immediately during development.
# FastAPI dev server (hot reload enabled)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080", "--reload"]Environment-specific Configuration
.env File Management
# .env.development (local development)
DATABASE_URL=postgresql://user:pass@localhost:5432/myapp_dev
DEBUG=true
API_URL=http://localhost:8080
# .env.staging (staging)
DATABASE_URL=postgresql://user:pass@staging-db:5432/myapp_staging
DEBUG=true
API_URL=https://staging-api.myapp.com
# .env.production (production)
DATABASE_URL=postgresql://user:pass@prod-db:5432/myapp
DEBUG=false
API_URL=https://api.myapp.comAdd to .gitignore
Never commit .env files to Git.
Instead, create an .env.example to share a template.
.env.example Example
# Database
DATABASE_URL=postgresql://user:password@host:5432/dbname
# API Settings
API_URL=https://api.example.com
DEBUG=false
# Authentication
JWT_SECRET=your-secret-key-hereCloud vs Local
| Scenario | Recommendation | Reason |
|---|---|---|
| Solo development | docker-compose | Free, fast feedback |
| Team development | Cloud DB + local app | Need to share data |
| Staging | Cloud | Similar to production |
| Production | Cloud | Stability, scalability |
Cost Optimization Tips
- Only during dev hours use cloud DB (usage-based billing)
- Leverage free tiers (Supabase, Neon, PlanetScale)
- Keep staging environments at minimum specs
- Test locally thoroughly before deploying to the cloud
Deep Dive Articles
Next Steps
If your development environment setup is complete, let's learn about operations next. In Cycle 6: Ops, you will learn about deployment strategies, monitoring, and cost management.