Docker is like a shipping container for software. Instead of worrying about "works on my machine" problems, Docker packages your entire application with everything it needs to run - code, dependencies, and settings - into portable containers.
Why Docker?
- Consistent Environment: Everyone runs the same setup
- Easy Setup: No complex local installations
- Isolated Services: Database, backend, and tools run separately
- Resource Efficient: Start/stop services as needed
- Team Friendly: Same environment for all developers
- Docker Desktop - The main Docker application (download here)
- Git - For downloading the project code
- Node.js & Yarn - For running project scripts
- Open Docker Desktop and make sure it's running
- Open a terminal/command prompt
- Run
docker --versionto verify Docker is installed
Follow these steps to get your development environment running:
git clone <repository-url>
cd fcc
yarn install# Start development services (recommended)
yarn docker:up:dev
# Or start all services
yarn docker:up:all
# Alternative: Using Docker Compose directly
docker-compose -f docker-compose.dev.yml up -d postgres adminer backend-dev# Run migrations on development backend
yarn docker:migrate:dev
# Alternative: Manual command
docker-compose -f docker-compose.dev.yml exec backend-dev sh -c "cd /app && npm run migration:run"- API: Visit
http://localhost:3001/api(development server) - Database Viewer: Visit
http://localhost:8080(Adminer) - Login to Adminer: System:
PostgreSQL, Server:postgres, Username:postgres, Password:postgres, Database:fcc_dev
Purpose: Runs your API code with live reloading
Use cases: Development, testing new features, running migrations
Features:
- Hot Reload: Changes appear instantly without restarting
- Source Access: Can read your TypeScript files
- Development Tools: Better error messages and debugging
Purpose: Runs optimized, compiled version of your API
Use cases: Testing production builds, performance testing
Features:
- Fast: Optimized for speed
- Secure: Production-ready settings
- Compiled: Runs pre-built JavaScript (not source code)
Purpose: Stores all your application data
Database Credentials:
- System:
PostgreSQL - Host:
postgres - Port:
5432 - Database:
fcc_dev - Username:
postgres - Password:
postgres
Storage: Uses postgres_data volume to persist database files
Features:
- Persistent: Data survives container restarts via
postgres_datavolume - Health Checks: Automatically verifies it's working
- Auto Setup: Creates initial database structure
Purpose: Web interface to view and edit database data Use cases: Checking data, running quick queries, debugging
What are volumes? Special folders that persist data outside containers
Why do we have 2 volumes?
- Purpose: Stores your database files permanently
- Location:
/var/lib/postgresql/datainside PostgreSQL container - Why needed: Database data must survive container restarts/crashes
- Size: Usually small unless you have lots of data
- Purpose: Stores application log files
- Location:
/app/logsinside backend containers - Why needed: Logs help debug issues and track application behavior
- Size: Usually very small
Volume Creation Messages:
Volume "fcc_postgres_data" Created # Database storage
Volume "fcc_backend_logs" Created # Application logs# Start all services
yarn docker:up
# Shorthand commands
yarn docker:up:dev # Start only dev services (postgres, adminer, backend-dev)
yarn docker:down # Stop everything
yarn docker:restart # Restart all services# See which services are running
docker-compose -f docker-compose.dev.yml ps
# View logs from all services
yarn docker:logs
# View logs from specific service
docker-compose -f docker-compose.dev.yml logs -f backend-dev# RECOMMENDED: Run migrations on development backend
yarn docker:migrate:dev
# Alternative: Run migrations on production backend (not recommended for dev)
yarn docker:migrateWhat happens behind the scenes:
# 1. Build fresh image with source code
docker build --file apps/backend/Dockerfile --target build -t fcc-backend-build .
# 2. Run temporary container (auto-deleted when done)
docker run --rm --network fcc_fcc-network \
-e NX_DB_HOST=postgres \
-e NX_DB_PORT=5432 \
-e NX_DB_USERNAME=postgres \
-e NX_DB_PASSWORD=postgres \
-e NX_DB_DATABASE=fcc_dev \
fcc-backend-build npm run migration:runKey Benefits:
- Isolated: Doesn't touch your running containers
- Clean: Fresh build every time - no cached issues
- Recoverable: Works when other containers fail
- CI/CD Ready: Perfect for automated deployments
- Testable: Safe to test migrations without affecting dev environment
- Zero Cleanup: Container disappears automatically
Perfect for:
- Container crashes or corruption
- Automated deployment pipelines
- Testing migrations safely
- Recovery from migration failures
- Ensuring clean migration runs
# Build/rebuild Docker images
yarn docker:build
# Clean up everything (containers, volumes, networks)
yarn docker:clean# Access development backend (for debugging, running commands)
docker-compose -f docker-compose.dev.yml exec backend-dev sh
# Access production backend (rarely needed)
docker-compose -f docker-compose.dev.yml exec backend sh
# Access database (advanced users)
docker-compose -f docker-compose.dev.yml exec postgres bashProblem: Docker isn't installed or not in PATH
Solution:
- Install Docker Desktop
- Restart your terminal/command prompt
- Try
docker --versionto verify
Problem: Another application is using ports 3000, 3001, 5432, or 8080
Solution:
- Find what's using the port:
netstat -ano | findstr :3000(Windows) orlsof -i :3000(Mac/Linux) - Stop the conflicting application or change Docker ports in
docker-compose.dev.yml
Problem: Docker is using too much disk space
Solution:
# Clean up unused Docker resources
docker system prune -a
yarn docker:cleanProblem: Database migrations failing
Solution:
- Make sure you're using
backend-dev(notbackend) for migrations - Check database is healthy first
- Verify migration files exist in
apps/backend/src/migrations/
If regular migrations fail, try:
# Or restart services and try again
yarn docker:restart
yarn docker:migrate:dev# Start production backend alongside development
docker-compose -f docker-compose.dev.yml up -d backend
# Test production at http://localhost:3000
# Development still available at http://localhost:3001- Volumes keep Postgres data between restarts. Do not remove unless you want a fresh DB.
- Adminer runs in a container so it can reach the Postgres service using the internal Docker hostname
postgres.
- This compose file is for development only. Replace default passwords and use secrets in production.