Local Production-Like Environment Setup
This guide helps developers set up a local environment that mirrors the production deployment, allowing you to test features in a production-like setup before deploying.
Overview
The local production environment includes all the same services as production:
- Backend API: Node.js/Fastify application
- Frontend: React/Vite application
- Database: PostgreSQL
- Reverse Proxy: Nginx
- Monitoring: Prometheus and Grafana
- Container Management: Portainer
- Database Management: Adminer
- Metrics Collection: cAdvisor and Node Exporter
Prerequisites
- Docker and Docker Compose installed
- Git
- At least 8GB RAM available for containers
- Ports 80, 443, 3000, 4000, 5432, 9001, 9090 available
Quick Start
-
Clone the repositories:
| Bash |
|---|
| # Clone the main PRS repositories
git clone https://gitlab.stratpoint.dev/cityland/prs-backend
git clone https://gitlab.stratpoint.dev/cityland/prs-frontend
# Clone the deployment repository
git clone https://gitlab.stratpoint.dev/cityland/deployment
cd deployment
|
-
Set up the local development environment:
| Bash |
|---|
| # Create local configuration directory
mkdir -p local
# Copy and customize environment files
cp .env.example local/.env.local
cp backend.env local/backend.local.env
cp frontend.env local/frontend.local.env
|
-
Configure environment variables (see Configuration section below)
-
Start the environment:
| Bash |
|---|
| ./deploy-local.sh --build --up --init-db
|
-
Access the applications:
- PRS Application: http://localhost
- Grafana: http://localhost:3000 (admin/admin)
- Prometheus: http://localhost:9090
- Portainer: http://localhost:9001
- Adminer: http://localhost:8080
Directory Structure
| Text Only |
|---|
| # Repository structure
├── deployment/ # Deployment repository
│ ├── local/ # Local development configurations
│ │ ├── compose.local.yml # Local Docker Compose configuration
│ │ ├── .env.local # Local environment variables
│ │ ├── backend.local.env # Local backend environment
│ │ ├── frontend.local.env # Local frontend environment
│ │ └── deploy-local.sh # Local deployment script
│ ├── nginx/
│ │ └── local/ # Local Nginx configurations
│ │ └── default.conf # Local Nginx configuration
│ ├── prometheus/
│ │ └── local/ # Local Prometheus configurations
│ │ └── prometheus.yml # Local Prometheus configuration
│ ├── grafana/
│ │ └── local/ # Local Grafana configurations
│ │ ├── datasources/ # Grafana data sources
│ │ └── dashboards/ # Grafana dashboards
├── prs-backend/ # Backend repository
└── prs-frontend/ # Frontend repository
|
Configuration
Environment Variables (.env.local)
| Bash |
|---|
| # Database Configuration
POSTGRES_DB=prs_local
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin123
# API URLs
VITE_APP_API_URL=http://localhost/api
# Cloudflare (disabled for local)
CLOUDFLARE_TUNNEL_TOKEN=disabled
# Monitoring
GRAFANA_ADMIN_PASSWORD=admin
|
Backend Configuration (backend.local.env)
| Bash |
|---|
| # Application config
PORT=4000
HOST=0.0.0.0
JWT_SECRET=local-jwt-secret-key-for-development
NODE_ENV=development
OTP_KEY=U29tZVNlY3JldEtleVdpdGg2NEJ5dGVz
PASS_SECRET=12345
BYPASS_OTP=true
LOG_LEVEL=debug
DISABLE_REQUEST_LOGS=false
# Database configs
POSTGRES_SERVICE=postgres
POSTGRES_HOST=postgres
POSTGRES_DB=prs_local
POSTGRES_PORT=5432
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin123
DIALECT=postgres
POOL_MIN=0
POOL_MAX=5
POOL_ACQUIRE=30000
POOL_IDLE=10000
POOL_EVICTION=20000
DISABLE_SSL=true
# Root User
ROOT_USER_NAME=admin
ROOT_USER_EMAIL=admin@local.dev
ROOT_USER_PASSWORD=admin123
# API Integration (Mock endpoints for local development)
CITYLAND_API_URL=https://cmd-test.free.beeceptor.com
CITYLAND_ACCOUNTING_URL=https://cityland-accounting.free.beeceptor.com
# Department Association
ASSOCIATION_DEPARTMENT_CODE=10
# PLG Stack Integration
PROMETHEUS_ENABLED=true
# Development Features
ENABLE_DEBUG_ROUTES=true
ENABLE_SWAGGER=true
CORS_ORIGIN=http://localhost:3000,http://localhost
|
Frontend Configuration (frontend.local.env)
| Bash |
|---|
| # API Configuration
VITE_APP_API_URL=http://localhost/api
VITE_APP_UPLOAD_URL=http://localhost/api/upload
# Development Features
VITE_APP_ENABLE_API_MOCKING=false
VITE_APP_ENABLE_DEVTOOLS=true
# PLG Stack Integration
VITE_APP_PROMETHEUS_GATEWAY=http://localhost:9091
VITE_APP_GRAFANA_URL=http://localhost:3000
# Logging Configuration
VITE_APP_LOG_LEVEL=debug
VITE_APP_LOG_BATCH_SIZE=10
VITE_APP_LOG_FLUSH_INTERVAL=5000
# Application Metadata
VITE_APP_APP_VERSION=1.0.0-local
VITE_APP_BUILD_ID=local-development
VITE_APP_ENVIRONMENT=local
|
Services Configuration
Local Docker Compose (compose.local.yml)
The local compose file includes all production services with development-friendly configurations:
- Development volumes: Source code mounted for hot reloading
- Debug ports: Additional ports exposed for debugging
- Development images: Images optimized for development
- Local networking: Simplified networking for local access
- Debug logging: Enhanced logging for development
Nginx Configuration (nginx/local/default.conf)
Local Nginx configuration includes:
- Frontend serving: Serves React development build
- API proxying: Proxies API requests to backend
- Static assets: Serves uploaded files and assets
- CORS headers: Proper CORS configuration for development
- Debug headers: Additional headers for debugging
Monitoring Stack
Prometheus (prometheus/local/prometheus.yml)
- Local targets: All services configured for local access
- Short intervals: Faster scraping for development
- Debug metrics: Additional metrics for development
Grafana (grafana/local/)
- Pre-configured dashboards: PRS-specific dashboards
- Local data sources: Prometheus and Loki configured
- Development panels: Additional panels for debugging
Development Workflow
Starting the Environment
| Bash |
|---|
| # Full environment startup
./deploy-local.sh --build --up --init-db
# Individual service management
./deploy-local.sh --restart backend
./deploy-local.sh --logs frontend
|
Development Commands
| Bash |
|---|
| # Database operations
./deploy-local.sh --migrate # Run migrations
./deploy-local.sh --seed # Run seeders
./deploy-local.sh --reset-db # Reset database
# Monitoring
./deploy-local.sh --logs # View all logs
./deploy-local.sh --logs backend # View backend logs
./deploy-local.sh --status # Check service status
# Cleanup
./deploy-local.sh --clean # Clean Docker resources
./deploy-local.sh --down # Stop all services
|
Hot Reloading
The local environment supports hot reloading for both frontend and backend:
- Frontend: Vite dev server with HMR
- Backend: Nodemon for automatic restarts
- Nginx: Configuration reloading without restart
Debugging
Backend Debugging
| Bash |
|---|
| # Enable debug mode
docker compose -f compose.local.yml exec backend npm run debug
# View debug logs
docker compose -f compose.local.yml logs -f backend
|
Frontend Debugging
| Bash |
|---|
| # Access development tools
# Open http://localhost:3000 in browser
# React DevTools and Redux DevTools available
# View frontend logs
docker compose -f compose.local.yml logs -f frontend
|
Database Management
Using Adminer
- Open http://localhost:8080
- Server:
postgres
- Username:
admin
- Password:
admin123
- Database:
prs_local
Direct Database Access
| Bash |
|---|
| # Connect to PostgreSQL
docker compose -f compose.local.yml exec postgres psql -U admin -d prs_local
# Backup database
./deploy-local.sh --backup-db
# Restore database
./deploy-local.sh --restore-db backup_file.sql
|
Monitoring and Observability
Grafana Dashboards
Pre-configured dashboards available:
- PRS Application Overview
- Request rates and response times
- Error rates and success rates
-
User activity and business metrics
-
Infrastructure Monitoring
- Container resource usage
-
Database performance
-
Business Intelligence
- Requisition workflow metrics
- User activity patterns
- System usage analytics
Prometheus Metrics
Key metrics available:
- Application Metrics: Request/response metrics, business events
- Infrastructure Metrics: CPU, memory, disk usage
- Database Metrics: Query performance, connection pools
Testing Production Features
Load Testing
| Bash |
|---|
| # Install k6 for load testing
npm install -g k6
# Run load tests
k6 run scripts/load-test.js
|
| Bash |
|---|
| # Monitor performance metrics
# Open Grafana: http://localhost:3000
# View "Performance Testing" dashboard
# Run performance tests
npm run test:performance
|
Security Testing
| Bash |
|---|
| # Test authentication flows
npm run test:auth
# Test authorization
npm run test:permissions
# Test input validation
npm run test:validation
|
Troubleshooting
Common Issues
Port Conflicts
| Bash |
|---|
| # Check port usage
netstat -tulpn | grep :80
# Stop conflicting services
sudo systemctl stop apache2
sudo systemctl stop nginx
|
Memory Issues
| Bash |
|---|
| # Check Docker memory usage
docker stats
# Increase Docker memory limit
# Docker Desktop: Settings > Resources > Memory
|
Database Connection Issues
| Bash |
|---|
| # Check database status
docker compose -f compose.local.yml ps postgres
# Reset database
./deploy-local.sh --down
docker volume rm deployment_postgres_data
./deploy-local.sh --up --init-db
|
Service Discovery Issues
| Bash |
|---|
| # Check network connectivity
docker compose -f compose.local.yml exec backend ping postgres
docker compose -f compose.local.yml exec frontend ping backend
# Restart networking
./deploy-local.sh --down
./deploy-local.sh --up
|
Log Analysis
| Bash |
|---|
| # View all service logs
./deploy-local.sh --logs
# Filter logs by service
./deploy-local.sh --logs backend | grep ERROR
# View real-time logs
docker compose -f compose.local.yml logs -f --tail=100
|
| Bash |
|---|
| # Check resource usage
docker stats
# Profile backend performance
docker compose -f compose.local.yml exec backend npm run profile
# Monitor database queries
docker compose -f compose.local.yml logs postgres | grep "duration:"
|
Production Parity
This local environment maintains parity with production in:
- Service Architecture: Same services and configurations
- Data Flow: Identical request/response patterns
- Security: Same authentication and authorization
- Monitoring: Same observability stack
- Performance: Similar performance characteristics
Differences from Production
- SSL/TLS: HTTP instead of HTTPS for simplicity
- Scaling: Single instance instead of multiple replicas
- Storage: Local volumes instead of cloud storage
- Networking: Simplified networking without load balancers
- Security: Relaxed security for development convenience
Next Steps
After setting up the local environment:
- Explore the Application: Test all features in the production-like environment
- Monitor Performance: Use Grafana dashboards to understand system behavior
- Test Integrations: Verify external API integrations work correctly
- Load Testing: Run load tests to understand system limits
- Deploy to Production: Use the same configurations for production deployment
For production deployment, refer to the Cityland Deployment Repository which contains the complete production deployment configuration.
Local Development Files
Docker Compose Configuration (compose.local.yml)
| YAML |
|---|
| services:
# Backend API (Development Mode)
backend:
build:
context: ../prs-backend
dockerfile: Dockerfile.dev
target: development
image: prs-backend:local
restart: unless-stopped
depends_on:
- postgres
env_file:
- ./local/backend.local.env
volumes:
- ../prs-backend:/usr/app
- /usr/app/node_modules
- backend_logs:/usr/app/logs
- ../prs-backend/upload:/usr/app/upload
ports:
- "4000:4000"
- "9229:9229" # Debug port
networks:
- app_network
- monitoring_network
command: npm run dev
# Frontend (Development Mode)
frontend:
build:
context: ../prs-frontend
dockerfile: Dockerfile.dev
target: development
image: prs-frontend:local
restart: unless-stopped
env_file:
- ./local/frontend.local.env
volumes:
- ../prs-frontend:/usr/app
- /usr/app/node_modules
ports:
- "3000:3000"
- "24678:24678" # Vite HMR port
networks:
- app_network
command: npm run dev
# Database
postgres:
image: postgres:13
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-prs_local}
POSTGRES_USER: ${POSTGRES_USER:-admin}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-admin123}
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./local/postgres/init:/docker-entrypoint-initdb.d
networks:
- app_network
# Nginx Reverse Proxy
nginx:
image: nginx:latest
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./nginx/local/default.conf:/etc/nginx/conf.d/default.conf
- ../prs-backend/upload:/usr/share/nginx/html/upload
depends_on:
- backend
- frontend
networks:
- app_network
- monitoring_network
# Prometheus for metrics
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus/local/prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus/local/alerts:/etc/prometheus/alerts
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--web.enable-lifecycle'
- '--web.enable-admin-api'
- '--storage.tsdb.retention.time=7d'
networks:
- monitoring_network
# Grafana for visualization
grafana:
image: grafana/grafana:latest
restart: unless-stopped
ports:
- "3001:3000" # Mapped to 3001 to avoid conflict with frontend
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/local/provisioning:/etc/grafana/provisioning
- ./grafana/local/dashboards:/var/lib/grafana/dashboards
depends_on:
- prometheus
networks:
- monitoring_network
# Portainer for container management
portainer:
image: portainer/portainer-ce:latest
restart: unless-stopped
ports:
- "9001:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
networks:
- monitoring_network
# Adminer for database management
adminer:
image: adminer:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
ADMINER_DEFAULT_SERVER: postgres
ADMINER_DESIGN: hydra
networks:
- app_network
# cAdvisor for container metrics
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
restart: unless-stopped
ports:
- "8081:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
privileged: true
devices:
- /dev/kmsg
networks:
- monitoring_network
# Node Exporter for system metrics
node-exporter:
image: prom/node-exporter:latest
restart: unless-stopped
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
networks:
- monitoring_network
networks:
app_network:
driver: bridge
monitoring_network:
driver: bridge
volumes:
postgres_data:
backend_logs:
prometheus_data:
grafana_data:
portainer_data:
|
Local Deployment Script (deploy-local.sh)
| Bash |
|---|
| #!/bin/bash
# Local Development Deployment Script for PRS
# This script manages the local development environment
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
COMPOSE_FILE="compose.local.yml"
ENV_FILE="local/.env.local"
# Display help message
function show_help {
echo -e "${BLUE}PRS Local Development Environment${NC}"
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -b, --build Build all containers"
echo " -u, --up Start all containers"
echo " -d, --down Stop all containers"
echo " -r, --restart [service] Restart all containers or specific service"
echo " -m, --migrate Run database migrations"
echo " -s, --seed Run database seeders"
echo " -l, --logs [service] Show logs for all services or specific service"
echo " -c, --clean Clean up unused Docker resources"
echo " --init-db Initialize the database (migrate + seed)"
echo " --reset-db Reset the database (drop + recreate + migrate + seed)"
echo " --backup-db Backup the database"
echo " --restore-db [file] Restore the database from backup"
echo " --status Show status of all services"
echo " --setup Initial setup (create env files)"
echo ""
echo "Examples:"
echo " $0 --setup # Initial setup"
echo " $0 --build --up --init-db # Full environment startup"
echo " $0 --restart backend # Restart only backend service"
echo " $0 --logs frontend # View frontend logs"
}
# Check if Docker is running
function check_docker {
if ! docker info > /dev/null 2>&1; then
echo -e "${RED}Error: Docker is not running or not installed${NC}"
exit 1
fi
if ! docker compose version > /dev/null 2>&1; then
echo -e "${RED}Error: docker compose is not installed or not available${NC}"
exit 1
fi
}
# Create local environment files
function setup_env {
echo -e "${BLUE}Setting up local environment files...${NC}"
# Create local directory
mkdir -p local/{postgres,nginx,prometheus,grafana,loki}
# Create .env.local if it doesn't exist
if [[ ! -f "local/.env.local" ]]; then
cat > "local/.env.local" << EOF
# Database Configuration
POSTGRES_DB=prs_local
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin123
# API URLs
VITE_APP_API_URL=http://localhost/api
# Monitoring
GRAFANA_ADMIN_PASSWORD=admin
EOF
echo -e "${GREEN}Created local/.env.local${NC}"
fi
# Create backend.local.env if it doesn't exist
if [[ ! -f "local/backend.local.env" ]]; then
cat > "local/backend.local.env" << EOF
# Application config
PORT=4000
HOST=0.0.0.0
JWT_SECRET=local-jwt-secret-key-for-development
NODE_ENV=development
OTP_KEY=U29tZVNlY3JldEtleVdpdGg2NEJ5dGVz
PASS_SECRET=12345
BYPASS_OTP=true
LOG_LEVEL=debug
DISABLE_REQUEST_LOGS=false
# Database configs
POSTGRES_SERVICE=postgres
POSTGRES_HOST=postgres
POSTGRES_DB=prs_local
POSTGRES_PORT=5432
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin123
DIALECT=postgres
POOL_MIN=0
POOL_MAX=5
DISABLE_SSL=true
# Root User
ROOT_USER_NAME=admin
ROOT_USER_EMAIL=admin@local.dev
ROOT_USER_PASSWORD=admin123
# PLG Stack Integration
PROMETHEUS_ENABLED=true
# Development Features
ENABLE_DEBUG_ROUTES=true
ENABLE_SWAGGER=true
CORS_ORIGIN=http://localhost:3000,http://localhost
EOF
echo -e "${GREEN}Created local/backend.local.env${NC}"
fi
# Create frontend.local.env if it doesn't exist
if [[ ! -f "local/frontend.local.env" ]]; then
cat > "local/frontend.local.env" << EOF
# API Configuration
VITE_APP_API_URL=http://localhost/api
VITE_APP_UPLOAD_URL=http://localhost/api/upload
# Development Features
VITE_APP_ENABLE_API_MOCKING=false
VITE_APP_ENABLE_DEVTOOLS=true
# PLG Stack Integration
VITE_APP_PROMETHEUS_GATEWAY=http://localhost:9091
VITE_APP_GRAFANA_URL=http://localhost:3001
# Logging Configuration
VITE_APP_LOG_LEVEL=debug
VITE_APP_LOG_BATCH_SIZE=10
VITE_APP_LOG_FLUSH_INTERVAL=5000
# Application Metadata
VITE_APP_APP_VERSION=1.0.0-local
VITE_APP_BUILD_ID=local-development
VITE_APP_ENVIRONMENT=local
EOF
echo -e "${GREEN}Created local/frontend.local.env${NC}"
fi
echo -e "${GREEN}Environment setup complete!${NC}"
}
# Parse command line arguments
BUILD=false
UP=false
DOWN=false
RESTART=false
RESTART_SERVICE=""
MIGRATE=false
SEED=false
LOGS=false
LOGS_SERVICE=""
CLEAN=false
INIT_DB=false
RESET_DB=false
BACKUP_DB=false
RESTORE_DB=false
RESTORE_FILE=""
STATUS=false
SETUP=false
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-b|--build)
BUILD=true
shift
;;
-u|--up)
UP=true
shift
;;
-d|--down)
DOWN=true
shift
;;
-r|--restart)
RESTART=true
if [[ $2 && $2 != -* ]]; then
RESTART_SERVICE=$2
shift
fi
shift
;;
-m|--migrate)
MIGRATE=true
shift
;;
-s|--seed)
SEED=true
shift
;;
-l|--logs)
LOGS=true
if [[ $2 && $2 != -* ]]; then
LOGS_SERVICE=$2
shift
fi
shift
;;
-c|--clean)
CLEAN=true
shift
;;
--init-db)
INIT_DB=true
shift
;;
--reset-db)
RESET_DB=true
shift
;;
--backup-db)
BACKUP_DB=true
shift
;;
--restore-db)
RESTORE_DB=true
if [[ $2 && $2 != -* ]]; then
RESTORE_FILE=$2
shift
fi
shift
;;
--status)
STATUS=true
shift
;;
--setup)
SETUP=true
shift
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
show_help
exit 1
;;
esac
done
# Check Docker
check_docker
# If no options provided, show help
if [[ $BUILD == false && $UP == false && $DOWN == false && $RESTART == false && $MIGRATE == false && $SEED == false && $LOGS == false && $CLEAN == false && $INIT_DB == false && $RESET_DB == false && $BACKUP_DB == false && $RESTORE_DB == false && $STATUS == false && $SETUP == false ]]; then
show_help
exit 0
fi
# Setup environment
if [[ $SETUP == true ]]; then
setup_env
fi
# Build containers
if [[ $BUILD == true ]]; then
echo -e "${BLUE}Building containers...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE build
fi
# Start containers
if [[ $UP == true ]]; then
echo -e "${BLUE}Starting containers...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE up -d
echo -e "${GREEN}Containers started successfully!${NC}"
echo ""
echo -e "${BLUE}Access URLs:${NC}"
echo " PRS Application: http://localhost"
echo " Frontend Dev: http://localhost:3000"
echo " Backend API: http://localhost:4000"
echo " Grafana: http://localhost:3001 (admin/admin)"
echo " Prometheus: http://localhost:9090"
echo " Portainer: http://localhost:9001"
echo " MinIO Console: http://localhost:9002"
echo " Adminer: http://localhost:8080"
fi
# Stop containers
if [[ $DOWN == true ]]; then
echo -e "${BLUE}Stopping containers...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE down
fi
# Restart containers
if [[ $RESTART == true ]]; then
if [[ -n $RESTART_SERVICE ]]; then
echo -e "${BLUE}Restarting $RESTART_SERVICE...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE restart $RESTART_SERVICE
else
echo -e "${BLUE}Restarting all containers...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE restart
fi
fi
# Run migrations
if [[ $MIGRATE == true ]]; then
echo -e "${BLUE}Running migrations...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec backend npm run migrate
fi
# Run seeders
if [[ $SEED == true ]]; then
echo -e "${BLUE}Running seeders...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec backend npm run seed
fi
# Initialize database
if [[ $INIT_DB == true ]]; then
echo -e "${BLUE}Initializing database...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec backend npm run migrate
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec backend npm run seed
fi
# Reset database
if [[ $RESET_DB == true ]]; then
echo -e "${YELLOW}Resetting database...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE down
docker volume rm deployment_postgres_data 2>/dev/null || true
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE up -d postgres
sleep 5
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE up -d backend
sleep 10
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec backend npm run migrate
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec backend npm run seed
fi
# Show logs
if [[ $LOGS == true ]]; then
if [[ -n $LOGS_SERVICE ]]; then
echo -e "${BLUE}Showing logs for $LOGS_SERVICE...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE logs -f $LOGS_SERVICE
else
echo -e "${BLUE}Showing logs for all services...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE logs -f
fi
fi
# Show status
if [[ $STATUS == true ]]; then
echo -e "${BLUE}Service Status:${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE ps
fi
# Clean up
if [[ $CLEAN == true ]]; then
echo -e "${BLUE}Cleaning up Docker resources...${NC}"
docker system prune -f
fi
# Backup database
if [[ $BACKUP_DB == true ]]; then
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="prs_local_backup_$TIMESTAMP.sql"
echo -e "${BLUE}Backing up database to $BACKUP_FILE...${NC}"
docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec -T postgres pg_dump -U admin prs_local > $BACKUP_FILE
echo -e "${GREEN}Backup completed: $BACKUP_FILE${NC}"
fi
# Restore database
if [[ $RESTORE_DB == true ]]; then
if [[ ! -f $RESTORE_FILE ]]; then
echo -e "${RED}Error: Backup file $RESTORE_FILE not found${NC}"
exit 1
fi
echo -e "${BLUE}Restoring database from $RESTORE_FILE...${NC}"
cat $RESTORE_FILE | docker compose -f $COMPOSE_FILE --env-file $ENV_FILE exec -T postgres psql -U admin prs_local
echo -e "${GREEN}Restore completed${NC}"
fi
echo -e "${GREEN}Done!${NC}"
|
Nginx Configuration (nginx/local/default.conf)
| Nginx Configuration File |
|---|
| # Local development Nginx configuration
upstream backend_servers {
server backend:4000;
}
upstream frontend_servers {
server frontend:3000;
}
# Main server block
server {
listen 80;
server_name localhost;
# Increase client max body size for file uploads
client_max_body_size 100M;
# Frontend (React app)
location / {
proxy_pass http://frontend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support for HMR
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# CORS headers for development
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
}
# Backend API
location /api/ {
proxy_pass http://backend_servers/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# CORS headers for development
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
# Handle preflight requests
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
# Static file uploads
location /uploads/ {
alias /usr/share/nginx/html/upload/;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Health check endpoint
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
|