✨ MAJOR FEATURES: • Auto-zoom intelligence với smart bounds fitting • Enhanced 3D GPS markers với pulsing effects • Professional route display với 6-layer rendering • Status-based parking icons với availability indicators • Production-ready build optimizations 🗺️ AUTO-ZOOM FEATURES: • Smart bounds fitting cho GPS + selected parking • Adaptive padding (50px) cho visual balance • Max zoom control (level 16) để tránh quá gần • Dynamic centering khi không có selection 🎨 ENHANCED VISUALS: • 3D GPS marker với multi-layer pulse effects • Advanced parking icons với status colors • Selection highlighting với animation • Dimming system cho non-selected items 🛣️ ROUTE SYSTEM: • OpenRouteService API integration • Multi-layer route rendering (glow, shadow, main, animated) • Real-time distance & duration calculation • Visual route info trong popup 📱 PRODUCTION READY: • SSR safe với dynamic imports • Build errors resolved • Global deployment via Vercel • Optimized performance 🌍 DEPLOYMENT: • Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app • Bundle size: 22.8 kB optimized • Global CDN distribution • HTTPS enabled 💾 VERSION CONTROL: • MapView-v2.0.tsx backup created • MAPVIEW_VERSIONS.md documentation • Full version history tracking
511 lines
10 KiB
Markdown
511 lines
10 KiB
Markdown
# 🚀 Deployment Guide
|
|
|
|
This guide covers different deployment strategies for the Smart Parking Finder application.
|
|
|
|
## 📋 Table of Contents
|
|
|
|
1. [Development Deployment](#development-deployment)
|
|
2. [Production Deployment](#production-deployment)
|
|
3. [Cloud Deployment Options](#cloud-deployment-options)
|
|
4. [Environment Configuration](#environment-configuration)
|
|
5. [Monitoring & Logging](#monitoring--logging)
|
|
6. [Backup & Recovery](#backup--recovery)
|
|
7. [Troubleshooting](#troubleshooting)
|
|
|
|
## 🛠️ Development Deployment
|
|
|
|
### Quick Start
|
|
|
|
```bash
|
|
# 1. Clone and setup
|
|
git clone <repository-url>
|
|
cd smart-parking-finder
|
|
./setup.sh
|
|
|
|
# 2. Start development environment
|
|
docker-compose up -d
|
|
|
|
# 3. Start development servers
|
|
cd frontend && npm run dev &
|
|
cd backend && npm run start:dev &
|
|
```
|
|
|
|
### Development Services
|
|
|
|
- **Frontend**: http://localhost:3000
|
|
- **Backend API**: http://localhost:3001
|
|
- **PostgreSQL**: localhost:5432
|
|
- **Redis**: localhost:6379
|
|
- **Valhalla**: http://localhost:8002
|
|
- **pgAdmin**: http://localhost:5050 (with `--profile tools`)
|
|
|
|
## 🏭 Production Deployment
|
|
|
|
### Docker Compose Production
|
|
|
|
```bash
|
|
# 1. Create production environment
|
|
cp docker-compose.yml docker-compose.prod.yml
|
|
|
|
# 2. Update production configuration
|
|
# Edit docker-compose.prod.yml with production settings
|
|
|
|
# 3. Deploy
|
|
docker-compose -f docker-compose.prod.yml up -d
|
|
```
|
|
|
|
### Production Docker Compose
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile.prod
|
|
ports:
|
|
- "80:3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- NEXT_PUBLIC_API_URL=https://api.yourparking.com
|
|
restart: unless-stopped
|
|
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile.prod
|
|
ports:
|
|
- "3001:3001"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
- REDIS_URL=${REDIS_URL}
|
|
- JWT_SECRET=${JWT_SECRET}
|
|
restart: unless-stopped
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
ports:
|
|
- "443:443"
|
|
- "80:80"
|
|
volumes:
|
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
|
- ./nginx/ssl:/etc/nginx/ssl
|
|
depends_on:
|
|
- frontend
|
|
- backend
|
|
restart: unless-stopped
|
|
|
|
postgres:
|
|
image: postgis/postgis:15-3.3
|
|
environment:
|
|
- POSTGRES_DB=${POSTGRES_DB}
|
|
- POSTGRES_USER=${POSTGRES_USER}
|
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
restart: unless-stopped
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
volumes:
|
|
- redis_data:/data
|
|
restart: unless-stopped
|
|
|
|
valhalla:
|
|
build: ./valhalla
|
|
volumes:
|
|
- valhalla_data:/data
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
postgres_data:
|
|
redis_data:
|
|
valhalla_data:
|
|
```
|
|
|
|
## ☁️ Cloud Deployment Options
|
|
|
|
### 1. DigitalOcean Droplet
|
|
|
|
**Recommended for small to medium deployments**
|
|
|
|
```bash
|
|
# 1. Create Droplet (4GB RAM minimum for Valhalla)
|
|
doctl compute droplet create parking-app \
|
|
--size s-2vcpu-4gb \
|
|
--image ubuntu-22-04-x64 \
|
|
--region sgp1
|
|
|
|
# 2. Install Docker
|
|
ssh root@your-droplet-ip
|
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
|
sh get-docker.sh
|
|
|
|
# 3. Deploy application
|
|
git clone <repository-url>
|
|
cd smart-parking-finder
|
|
docker-compose -f docker-compose.prod.yml up -d
|
|
```
|
|
|
|
### 2. AWS EC2 + RDS
|
|
|
|
**Recommended for scalable production**
|
|
|
|
```bash
|
|
# 1. Launch EC2 instance (t3.medium minimum)
|
|
# 2. Setup RDS PostgreSQL with PostGIS
|
|
# 3. Setup ElastiCache Redis
|
|
# 4. Deploy application containers
|
|
|
|
# User data script for EC2:
|
|
#!/bin/bash
|
|
yum update -y
|
|
yum install -y docker git
|
|
systemctl start docker
|
|
systemctl enable docker
|
|
usermod -a -G docker ec2-user
|
|
|
|
# Clone and deploy
|
|
git clone <repository-url> /opt/parking-app
|
|
cd /opt/parking-app
|
|
docker-compose -f docker-compose.aws.yml up -d
|
|
```
|
|
|
|
### 3. Google Cloud Platform
|
|
|
|
**Using Cloud Run and Cloud SQL**
|
|
|
|
```bash
|
|
# 1. Build and push images
|
|
gcloud builds submit --tag gcr.io/PROJECT_ID/parking-frontend ./frontend
|
|
gcloud builds submit --tag gcr.io/PROJECT_ID/parking-backend ./backend
|
|
|
|
# 2. Deploy to Cloud Run
|
|
gcloud run deploy parking-frontend \
|
|
--image gcr.io/PROJECT_ID/parking-frontend \
|
|
--platform managed \
|
|
--region asia-southeast1
|
|
|
|
gcloud run deploy parking-backend \
|
|
--image gcr.io/PROJECT_ID/parking-backend \
|
|
--platform managed \
|
|
--region asia-southeast1
|
|
```
|
|
|
|
### 4. Kubernetes Deployment
|
|
|
|
**For large-scale deployments**
|
|
|
|
```yaml
|
|
# k8s/namespace.yaml
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: parking-finder
|
|
|
|
---
|
|
# k8s/configmap.yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: app-config
|
|
namespace: parking-finder
|
|
data:
|
|
DATABASE_HOST: "postgres-service"
|
|
REDIS_HOST: "redis-service"
|
|
VALHALLA_URL: "http://valhalla-service:8002"
|
|
|
|
---
|
|
# k8s/deployment.yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: frontend-deployment
|
|
namespace: parking-finder
|
|
spec:
|
|
replicas: 3
|
|
selector:
|
|
matchLabels:
|
|
app: frontend
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: frontend
|
|
spec:
|
|
containers:
|
|
- name: frontend
|
|
image: your-registry/parking-frontend:latest
|
|
ports:
|
|
- containerPort: 3000
|
|
envFrom:
|
|
- configMapRef:
|
|
name: app-config
|
|
```
|
|
|
|
## 🔧 Environment Configuration
|
|
|
|
### Production Environment Variables
|
|
|
|
```bash
|
|
# .env.production
|
|
NODE_ENV=production
|
|
|
|
# Database
|
|
DATABASE_URL=postgresql://user:pass@db-host:5432/parking_db
|
|
POSTGRES_SSL=true
|
|
|
|
# Redis
|
|
REDIS_URL=redis://redis-host:6379
|
|
REDIS_SSL=true
|
|
|
|
# Security
|
|
JWT_SECRET=your-super-secure-jwt-secret-256-bit
|
|
JWT_EXPIRATION=1h
|
|
CORS_ORIGIN=https://yourparking.com
|
|
|
|
# APIs
|
|
VALHALLA_URL=http://valhalla:8002
|
|
MAP_TILES_URL=https://tile.openstreetmap.org/{z}/{x}/{y}.png
|
|
|
|
# Monitoring
|
|
SENTRY_DSN=your-sentry-dsn
|
|
LOG_LEVEL=info
|
|
|
|
# Performance
|
|
REDIS_CACHE_TTL=3600
|
|
DB_POOL_SIZE=10
|
|
API_RATE_LIMIT=100
|
|
```
|
|
|
|
### SSL Configuration
|
|
|
|
```nginx
|
|
# nginx/nginx.conf
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name yourparking.com;
|
|
|
|
ssl_certificate /etc/nginx/ssl/cert.pem;
|
|
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
|
|
|
# Frontend
|
|
location / {
|
|
proxy_pass http://frontend:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
}
|
|
|
|
# Backend API
|
|
location /api {
|
|
proxy_pass http://backend:3001;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
}
|
|
|
|
# WebSocket support
|
|
location /ws {
|
|
proxy_pass http://backend:3001;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
}
|
|
```
|
|
|
|
## 📊 Monitoring & Logging
|
|
|
|
### Docker Logging
|
|
|
|
```yaml
|
|
# docker-compose.monitoring.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
prometheus:
|
|
image: prom/prometheus
|
|
ports:
|
|
- "9090:9090"
|
|
volumes:
|
|
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
|
|
|
|
grafana:
|
|
image: grafana/grafana
|
|
ports:
|
|
- "3001:3000"
|
|
environment:
|
|
- GF_SECURITY_ADMIN_PASSWORD=admin
|
|
volumes:
|
|
- grafana_data:/var/lib/grafana
|
|
|
|
node-exporter:
|
|
image: prom/node-exporter
|
|
ports:
|
|
- "9100:9100"
|
|
|
|
volumes:
|
|
grafana_data:
|
|
```
|
|
|
|
### Application Monitoring
|
|
|
|
```typescript
|
|
// backend/src/monitoring/metrics.ts
|
|
import { createPrometheusMetrics } from '@prometheus/client';
|
|
|
|
export const metrics = {
|
|
httpRequests: new Counter({
|
|
name: 'http_requests_total',
|
|
help: 'Total HTTP requests',
|
|
labelNames: ['method', 'route', 'status']
|
|
}),
|
|
|
|
routeCalculationTime: new Histogram({
|
|
name: 'route_calculation_duration_seconds',
|
|
help: 'Route calculation duration',
|
|
buckets: [0.1, 0.5, 1, 2, 5]
|
|
}),
|
|
|
|
databaseQueries: new Counter({
|
|
name: 'database_queries_total',
|
|
help: 'Total database queries',
|
|
labelNames: ['operation', 'table']
|
|
})
|
|
};
|
|
```
|
|
|
|
## 💾 Backup & Recovery
|
|
|
|
### Database Backup
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# backup.sh
|
|
|
|
# Variables
|
|
BACKUP_DIR="/opt/backups"
|
|
DATE=$(date +%Y%m%d_%H%M%S)
|
|
DB_NAME="parking_db"
|
|
|
|
# Create backup
|
|
docker-compose exec postgres pg_dump \
|
|
-U parking_user \
|
|
-h localhost \
|
|
-d $DB_NAME \
|
|
--clean \
|
|
--if-exists \
|
|
--create \
|
|
> "$BACKUP_DIR/db_backup_$DATE.sql"
|
|
|
|
# Compress backup
|
|
gzip "$BACKUP_DIR/db_backup_$DATE.sql"
|
|
|
|
# Keep only last 7 days
|
|
find $BACKUP_DIR -name "db_backup_*.sql.gz" -mtime +7 -delete
|
|
|
|
echo "Backup completed: db_backup_$DATE.sql.gz"
|
|
```
|
|
|
|
### Automated Backup with Cron
|
|
|
|
```bash
|
|
# Add to crontab: crontab -e
|
|
# Daily backup at 2 AM
|
|
0 2 * * * /opt/parking-app/scripts/backup.sh >> /var/log/backup.log 2>&1
|
|
|
|
# Weekly full system backup
|
|
0 3 * * 0 /opt/parking-app/scripts/full-backup.sh >> /var/log/backup.log 2>&1
|
|
```
|
|
|
|
## 🔍 Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Valhalla not starting**
|
|
```bash
|
|
# Check OSM data
|
|
ls -la valhalla/custom_files/
|
|
|
|
# Check logs
|
|
docker-compose logs valhalla
|
|
|
|
# Verify memory allocation
|
|
docker stats valhalla
|
|
```
|
|
|
|
2. **Database connection issues**
|
|
```bash
|
|
# Test connection
|
|
docker-compose exec postgres psql -U parking_user -d parking_db
|
|
|
|
# Check network
|
|
docker network ls
|
|
docker network inspect parking-finder_parking-network
|
|
```
|
|
|
|
3. **High memory usage**
|
|
```bash
|
|
# Monitor services
|
|
docker stats
|
|
|
|
# Optimize Valhalla cache
|
|
# Edit valhalla.json: reduce max_cache_size
|
|
```
|
|
|
|
### Health Checks
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# health-check.sh
|
|
|
|
echo "=== Health Check ==="
|
|
|
|
# Frontend
|
|
curl -f http://localhost:3000 || echo "❌ Frontend down"
|
|
|
|
# Backend
|
|
curl -f http://localhost:3001/health || echo "❌ Backend down"
|
|
|
|
# Database
|
|
docker-compose exec postgres pg_isready -U parking_user || echo "❌ Database down"
|
|
|
|
# Redis
|
|
docker-compose exec redis redis-cli ping || echo "❌ Redis down"
|
|
|
|
# Valhalla
|
|
curl -f http://localhost:8002/status || echo "❌ Valhalla down"
|
|
|
|
echo "=== Check complete ==="
|
|
```
|
|
|
|
### Performance Optimization
|
|
|
|
```yaml
|
|
# docker-compose.optimized.yml
|
|
services:
|
|
backend:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 1G
|
|
cpus: '0.5'
|
|
reservations:
|
|
memory: 512M
|
|
cpus: '0.25'
|
|
|
|
valhalla:
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 4G
|
|
cpus: '2'
|
|
reservations:
|
|
memory: 2G
|
|
cpus: '1'
|
|
```
|
|
|
|
---
|
|
|
|
For additional support, refer to the [main README](../README.md) or contact the development team.
|