feat: Create PM2 + Docker production deployment system
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
- Replaced old production script with PM2-based deployment - Created start-production.sh: automated startup script - Starts Docker containers for databases - Waits for database health checks - Runs migrations automatically - Builds backend/frontend if needed - Starts PM2 processes with ecosystem.config.js - Verifies all services are running - Created stop-production.sh: graceful shutdown script - Stops PM2 processes - Stops Docker containers - Verifies shutdown - Created PRODUCTION_DEPLOYMENT.md: comprehensive deployment guide - Prerequisites and installation steps - Configuration instructions - Nginx reverse proxy setup - SSL certificate setup with Certbot - Management commands for PM2 and Docker - Backup strategy - Troubleshooting guide - Security checklist Production setup: - Backend: Port 3020 → api.parentflowapp.com - Frontend: Port 3030 → web.parentflowapp.com - Docker: PostgreSQL, Redis, MongoDB, MinIO - PM2: Backend and Frontend applications - Target: Server 10.0.0.240 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
453
PRODUCTION_DEPLOYMENT.md
Normal file
453
PRODUCTION_DEPLOYMENT.md
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
# ParentFlow Production Deployment Guide
|
||||||
|
|
||||||
|
**Target Server**: 10.0.0.240
|
||||||
|
**Deployment Method**: PM2 + Docker
|
||||||
|
**Last Updated**: October 6, 2025
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Production deployment uses a hybrid approach:
|
||||||
|
- **Docker Compose**: For databases (PostgreSQL, Redis, MongoDB, MinIO)
|
||||||
|
- **PM2**: For application services (Backend, Frontend)
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Server: 10.0.0.240 │
|
||||||
|
├─────────────────────────────────────────────┤
|
||||||
|
│ PM2 Processes: │
|
||||||
|
│ - Backend: Port 3020 (Node.js/NestJS) │
|
||||||
|
│ - Frontend: Port 3030 (Next.js) │
|
||||||
|
├─────────────────────────────────────────────┤
|
||||||
|
│ Docker Containers: │
|
||||||
|
│ - PostgreSQL: Port 5432 │
|
||||||
|
│ - Redis: Port 6379 │
|
||||||
|
│ - MongoDB: Port 27017 │
|
||||||
|
│ - MinIO: Port 9000 (API) │
|
||||||
|
│ Port 9001 (Console) │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
↓ ↓
|
||||||
|
api.parentflowapp.com web.parentflowapp.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### 1. Install Required Software
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install Node.js 18+ and npm
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||||
|
sudo apt-get install -y nodejs
|
||||||
|
|
||||||
|
# Install PM2 globally
|
||||||
|
sudo npm install -g pm2
|
||||||
|
|
||||||
|
# Install Docker
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
|
||||||
|
# Install Docker Compose
|
||||||
|
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||||
|
sudo chmod +x /usr/local/bin/docker-compose
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Clone Repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /root
|
||||||
|
git clone https://git.noru1.ro/andrei/maternal-app.git
|
||||||
|
cd maternal-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Install Dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend dependencies
|
||||||
|
cd maternal-app/maternal-app-backend
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Frontend dependencies
|
||||||
|
cd ../../maternal-web
|
||||||
|
npm install
|
||||||
|
cd ../..
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### 1. Environment Variables
|
||||||
|
|
||||||
|
Copy the example environment file and update with production values:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.production.example .env.production
|
||||||
|
nano .env.production
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critical variables to update:**
|
||||||
|
- `POSTGRES_PASSWORD`: Strong password for PostgreSQL
|
||||||
|
- `REDIS_PASSWORD`: Strong password for Redis
|
||||||
|
- `MONGO_PASSWORD`: Strong password for MongoDB
|
||||||
|
- `JWT_SECRET`: 64-character random string
|
||||||
|
- `JWT_REFRESH_SECRET`: Different 64-character random string
|
||||||
|
- `OPENAI_API_KEY`: Your OpenAI API key (for AI features)
|
||||||
|
|
||||||
|
Generate secure secrets:
|
||||||
|
```bash
|
||||||
|
# Generate JWT secrets
|
||||||
|
openssl rand -base64 64
|
||||||
|
openssl rand -base64 64
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Update ecosystem.config.js
|
||||||
|
|
||||||
|
Ensure the production environment variables in `ecosystem.config.js` match your `.env.production` file.
|
||||||
|
|
||||||
|
### 3. Configure Nginx (Reverse Proxy)
|
||||||
|
|
||||||
|
Create Nginx configuration for domain routing:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# /etc/nginx/sites-available/parentflow
|
||||||
|
|
||||||
|
# Backend API
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name api.parentflowapp.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3020;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name web.parentflowapp.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3030;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable the site:
|
||||||
|
```bash
|
||||||
|
sudo ln -s /etc/nginx/sites-available/parentflow /etc/nginx/sites-enabled/
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. SSL Certificates (Optional but Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install Certbot
|
||||||
|
sudo apt-get install certbot python3-certbot-nginx
|
||||||
|
|
||||||
|
# Obtain certificates
|
||||||
|
sudo certbot --nginx -d api.parentflowapp.com -d web.parentflowapp.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### First-Time Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /root/maternal-app
|
||||||
|
|
||||||
|
# Start production environment
|
||||||
|
./start-production.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will:
|
||||||
|
1. ✅ Start Docker containers (databases)
|
||||||
|
2. ✅ Wait for databases to be healthy
|
||||||
|
3. ✅ Run database migrations
|
||||||
|
4. ✅ Build backend (if needed)
|
||||||
|
5. ✅ Build frontend (if needed)
|
||||||
|
6. ✅ Start PM2 processes
|
||||||
|
7. ✅ Verify all services
|
||||||
|
|
||||||
|
### Subsequent Deployments
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /root/maternal-app
|
||||||
|
|
||||||
|
# Pull latest changes
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Rebuild applications
|
||||||
|
cd maternal-app/maternal-app-backend
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
cd ../../maternal-web
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
|
||||||
|
# Restart PM2 processes
|
||||||
|
pm2 restart all
|
||||||
|
|
||||||
|
# Or use the full restart script
|
||||||
|
./stop-production.sh
|
||||||
|
./start-production.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Management Commands
|
||||||
|
|
||||||
|
### PM2 Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View process status
|
||||||
|
pm2 status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
pm2 logs
|
||||||
|
|
||||||
|
# View specific service logs
|
||||||
|
pm2 logs parentflow-backend
|
||||||
|
pm2 logs parentflow-frontend
|
||||||
|
|
||||||
|
# Restart services
|
||||||
|
pm2 restart all
|
||||||
|
pm2 restart parentflow-backend
|
||||||
|
pm2 restart parentflow-frontend
|
||||||
|
|
||||||
|
# Stop services
|
||||||
|
pm2 stop all
|
||||||
|
|
||||||
|
# Delete processes
|
||||||
|
pm2 delete all
|
||||||
|
|
||||||
|
# Save PM2 process list
|
||||||
|
pm2 save
|
||||||
|
|
||||||
|
# Setup PM2 to start on system boot
|
||||||
|
pm2 startup
|
||||||
|
pm2 save
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View running containers
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker logs parentflow-postgres-prod
|
||||||
|
docker logs parentflow-redis-prod
|
||||||
|
docker logs parentflow-mongodb-prod
|
||||||
|
docker logs parentflow-minio-prod
|
||||||
|
|
||||||
|
# Follow logs in real-time
|
||||||
|
docker logs -f parentflow-postgres-prod
|
||||||
|
|
||||||
|
# Access database shell
|
||||||
|
docker exec -it parentflow-postgres-prod psql -U parentflow_user -d parentflow_production
|
||||||
|
|
||||||
|
# Access Redis CLI
|
||||||
|
docker exec -it parentflow-redis-prod redis-cli -a parentflow_redis_password_2024
|
||||||
|
|
||||||
|
# Access MongoDB shell
|
||||||
|
docker exec -it parentflow-mongodb-prod mongo -u parentflow_admin -p parentflow_mongo_password_2024
|
||||||
|
|
||||||
|
# Stop all containers
|
||||||
|
docker-compose -f docker-compose.production.yml down
|
||||||
|
|
||||||
|
# Stop and remove volumes (WARNING: deletes data)
|
||||||
|
docker-compose -f docker-compose.production.yml down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Application Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start production
|
||||||
|
./start-production.sh
|
||||||
|
|
||||||
|
# Stop production
|
||||||
|
./stop-production.sh
|
||||||
|
|
||||||
|
# Check migration status
|
||||||
|
cd maternal-app/maternal-app-backend
|
||||||
|
./scripts/check-migrations.sh
|
||||||
|
|
||||||
|
# Run migrations manually
|
||||||
|
./scripts/master-migration.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
### Health Checks
|
||||||
|
|
||||||
|
- **Backend**: http://localhost:3020/api/health
|
||||||
|
- **Frontend**: http://localhost:3030
|
||||||
|
- **MinIO Console**: http://localhost:9001
|
||||||
|
|
||||||
|
### Log Files
|
||||||
|
|
||||||
|
PM2 logs are stored in:
|
||||||
|
- `~/.pm2/logs/parentflow-backend-out.log`
|
||||||
|
- `~/.pm2/logs/parentflow-backend-error.log`
|
||||||
|
- `~/.pm2/logs/parentflow-frontend-out.log`
|
||||||
|
- `~/.pm2/logs/parentflow-frontend-error.log`
|
||||||
|
|
||||||
|
Docker logs via:
|
||||||
|
```bash
|
||||||
|
docker logs <container-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Resources
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Monitor PM2 processes
|
||||||
|
pm2 monit
|
||||||
|
|
||||||
|
# Monitor Docker containers
|
||||||
|
docker stats
|
||||||
|
|
||||||
|
# System resources
|
||||||
|
htop
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backup Strategy
|
||||||
|
|
||||||
|
### Database Backups
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PostgreSQL backup
|
||||||
|
docker exec parentflow-postgres-prod pg_dump -U parentflow_user parentflow_production > backup-$(date +%Y%m%d).sql
|
||||||
|
|
||||||
|
# Restore PostgreSQL
|
||||||
|
cat backup-20251006.sql | docker exec -i parentflow-postgres-prod psql -U parentflow_user -d parentflow_production
|
||||||
|
|
||||||
|
# MongoDB backup
|
||||||
|
docker exec parentflow-mongodb-prod mongodump --username parentflow_admin --password parentflow_mongo_password_2024 --out /data/backup
|
||||||
|
|
||||||
|
# Redis backup (automatic with AOF persistence)
|
||||||
|
docker exec parentflow-redis-prod redis-cli -a parentflow_redis_password_2024 BGSAVE
|
||||||
|
```
|
||||||
|
|
||||||
|
### Automated Backups
|
||||||
|
|
||||||
|
Add to crontab:
|
||||||
|
```bash
|
||||||
|
# Daily database backup at 2 AM
|
||||||
|
0 2 * * * /root/maternal-app/scripts/backup-database.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Backend Won't Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
pm2 logs parentflow-backend --err
|
||||||
|
|
||||||
|
# Check if port is already in use
|
||||||
|
lsof -i:3020
|
||||||
|
|
||||||
|
# Verify database connection
|
||||||
|
docker exec -it parentflow-postgres-prod psql -U parentflow_user -d parentflow_production -c "SELECT version();"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend Won't Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
pm2 logs parentflow-frontend --err
|
||||||
|
|
||||||
|
# Rebuild frontend
|
||||||
|
cd maternal-web
|
||||||
|
rm -rf .next
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Connection Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if containers are running
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# Check container health
|
||||||
|
docker inspect parentflow-postgres-prod --format='{{.State.Health.Status}}'
|
||||||
|
|
||||||
|
# View container logs
|
||||||
|
docker logs parentflow-postgres-prod
|
||||||
|
```
|
||||||
|
|
||||||
|
### Migrations Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check migration status
|
||||||
|
cd maternal-app/maternal-app-backend
|
||||||
|
./scripts/check-migrations.sh
|
||||||
|
|
||||||
|
# Manually run specific migration
|
||||||
|
PGPASSWORD=parentflow_secure_password_2024 psql -h localhost -p 5432 -U parentflow_user -d parentflow_production -f src/database/migrations/V001_create_core_auth.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Checklist
|
||||||
|
|
||||||
|
- [ ] Updated all default passwords in `.env.production`
|
||||||
|
- [ ] Generated secure JWT secrets
|
||||||
|
- [ ] Configured firewall (ufw/iptables) to restrict database ports
|
||||||
|
- [ ] Enabled SSL certificates with Certbot
|
||||||
|
- [ ] Configured Nginx rate limiting
|
||||||
|
- [ ] Set up PM2 with non-root user (recommended)
|
||||||
|
- [ ] Enabled Docker container resource limits
|
||||||
|
- [ ] Configured backup strategy
|
||||||
|
- [ ] Set up monitoring/alerting
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
### PM2 Cluster Mode
|
||||||
|
|
||||||
|
For better performance, run backend in cluster mode:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// ecosystem.config.js
|
||||||
|
{
|
||||||
|
name: 'parentflow-backend',
|
||||||
|
instances: 'max', // Use all CPU cores
|
||||||
|
exec_mode: 'cluster',
|
||||||
|
// ... other settings
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Optimization
|
||||||
|
|
||||||
|
- Enable PostgreSQL connection pooling (already configured)
|
||||||
|
- Monitor slow queries
|
||||||
|
- Add indexes for frequently queried fields
|
||||||
|
- Configure Redis maxmemory policy
|
||||||
|
|
||||||
|
## CI/CD Integration
|
||||||
|
|
||||||
|
See `docs/REMAINING_FEATURES.md` for Gitea Actions workflow setup for automated deployments to 10.0.0.240.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues or questions:
|
||||||
|
- Check logs: `pm2 logs` and `docker logs`
|
||||||
|
- Review documentation: `/root/maternal-app/docs/`
|
||||||
|
- Check migration status: `./scripts/check-migrations.sh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: October 6, 2025
|
||||||
|
**Deployment Version**: 1.0.0
|
||||||
@@ -1,53 +1,224 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Start Production Servers Script
|
# ParentFlow Production Startup Script
|
||||||
|
# Uses PM2 for frontend/backend, Docker for databases
|
||||||
# Ports: Backend 3020, Frontend 3030
|
# Ports: Backend 3020, Frontend 3030
|
||||||
|
# Server: 10.0.0.240 (or localhost for local production testing)
|
||||||
|
|
||||||
echo "Starting ParentFlow Production Servers..."
|
set -e # Exit on any error
|
||||||
|
|
||||||
# Kill any existing processes on the ports
|
# Color codes
|
||||||
echo "Cleaning up existing processes..."
|
RED='\033[0;31m'
|
||||||
lsof -ti:3020 | xargs kill -9 2>/dev/null
|
GREEN='\033[0;32m'
|
||||||
lsof -ti:3030 | xargs kill -9 2>/dev/null
|
YELLOW='\033[1;33m'
|
||||||
sleep 2
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
# Start Backend on port 3020
|
echo "=========================================="
|
||||||
echo "Starting backend on port 3020..."
|
echo "ParentFlow Production Startup"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if PM2 is installed
|
||||||
|
if ! command -v pm2 &> /dev/null; then
|
||||||
|
echo -e "${RED}ERROR: PM2 is not installed!${NC}"
|
||||||
|
echo "Install PM2 globally with: npm install -g pm2"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Docker is installed
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo -e "${RED}ERROR: Docker is not installed!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if docker-compose is installed
|
||||||
|
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
|
||||||
|
echo -e "${RED}ERROR: Docker Compose is not installed!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 1: Start Docker services (databases)
|
||||||
|
echo -e "${BLUE}Step 1: Starting Docker services (databases)...${NC}"
|
||||||
|
if docker compose version &> /dev/null; then
|
||||||
|
docker compose -f docker-compose.production.yml up -d
|
||||||
|
else
|
||||||
|
docker-compose -f docker-compose.production.yml up -d
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ Docker services started${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Failed to start Docker services${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait for databases to be ready
|
||||||
|
echo -e "${YELLOW}Waiting for databases to be healthy...${NC}"
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Check database health
|
||||||
|
echo -e "${BLUE}Checking database health...${NC}"
|
||||||
|
MAX_RETRIES=30
|
||||||
|
RETRY_COUNT=0
|
||||||
|
|
||||||
|
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
||||||
|
POSTGRES_HEALTHY=$(docker inspect parentflow-postgres-prod --format='{{.State.Health.Status}}' 2>/dev/null || echo "starting")
|
||||||
|
REDIS_HEALTHY=$(docker inspect parentflow-redis-prod --format='{{.State.Health.Status}}' 2>/dev/null || echo "starting")
|
||||||
|
MONGO_HEALTHY=$(docker inspect parentflow-mongodb-prod --format='{{.State.Health.Status}}' 2>/dev/null || echo "starting")
|
||||||
|
|
||||||
|
if [ "$POSTGRES_HEALTHY" = "healthy" ] && [ "$REDIS_HEALTHY" = "healthy" ] && [ "$MONGO_HEALTHY" = "healthy" ]; then
|
||||||
|
echo -e "${GREEN}✓ All databases are healthy${NC}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Waiting for databases... ($RETRY_COUNT/$MAX_RETRIES)${NC}"
|
||||||
|
sleep 2
|
||||||
|
((RETRY_COUNT++))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
|
||||||
|
echo -e "${RED}✗ Databases failed to become healthy${NC}"
|
||||||
|
echo "Check Docker logs with: docker logs parentflow-postgres-prod"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 2: Run database migrations
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Step 2: Running database migrations...${NC}"
|
||||||
cd /root/maternal-app/maternal-app/maternal-app-backend
|
cd /root/maternal-app/maternal-app/maternal-app-backend
|
||||||
PORT=3020 API_PORT=3020 NODE_ENV=production nohup node dist/main.js > /root/maternal-app/logs/backend-prod.log 2>&1 &
|
|
||||||
BACKEND_PID=$!
|
|
||||||
echo "Backend started with PID: $BACKEND_PID"
|
|
||||||
|
|
||||||
# Start Frontend on port 3030
|
# Check if migration script exists
|
||||||
echo "Starting frontend on port 3030..."
|
if [ -f "./scripts/master-migration.sh" ]; then
|
||||||
|
echo -e "${YELLOW}Running master migration script...${NC}"
|
||||||
|
DATABASE_HOST=localhost \
|
||||||
|
DATABASE_PORT=5432 \
|
||||||
|
DATABASE_NAME=parentflow_production \
|
||||||
|
DATABASE_USER=parentflow_user \
|
||||||
|
DATABASE_PASSWORD=parentflow_secure_password_2024 \
|
||||||
|
./scripts/master-migration.sh || {
|
||||||
|
echo -e "${YELLOW}Warning: Migrations may have partially failed. Continuing...${NC}"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: Migration script not found. Skipping migrations.${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 3: Build backend (if needed)
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Step 3: Building backend...${NC}"
|
||||||
|
cd /root/maternal-app/maternal-app/maternal-app-backend
|
||||||
|
|
||||||
|
if [ ! -d "dist" ]; then
|
||||||
|
echo -e "${YELLOW}Building backend for the first time...${NC}"
|
||||||
|
npm run build
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}✗ Backend build failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Backend built successfully${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓ Backend dist directory exists${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 4: Build frontend (if needed)
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Step 4: Building frontend...${NC}"
|
||||||
cd /root/maternal-app/maternal-web
|
cd /root/maternal-app/maternal-web
|
||||||
PORT=3030 NODE_ENV=production nohup npm run start > /root/maternal-app/logs/frontend-prod.log 2>&1 &
|
|
||||||
FRONTEND_PID=$!
|
|
||||||
echo "Frontend started with PID: $FRONTEND_PID"
|
|
||||||
|
|
||||||
# Wait a moment for servers to start
|
if [ ! -d ".next" ]; then
|
||||||
|
echo -e "${YELLOW}Building frontend for the first time...${NC}"
|
||||||
|
npm run build
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}✗ Frontend build failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Frontend built successfully${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓ Frontend .next directory exists${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 5: Start PM2 processes
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Step 5: Starting PM2 processes...${NC}"
|
||||||
|
|
||||||
|
# Check if ecosystem.config.js exists
|
||||||
|
if [ ! -f "/root/maternal-app/ecosystem.config.js" ]; then
|
||||||
|
echo -e "${RED}✗ ecosystem.config.js not found${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stop any existing PM2 processes
|
||||||
|
echo -e "${YELLOW}Stopping any existing PM2 processes...${NC}"
|
||||||
|
pm2 delete all 2>/dev/null || true
|
||||||
|
|
||||||
|
# Start PM2 with ecosystem config (production environment)
|
||||||
|
cd /root/maternal-app
|
||||||
|
pm2 start ecosystem.config.js --env production
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ PM2 processes started${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Failed to start PM2 processes${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Save PM2 process list
|
||||||
|
pm2 save
|
||||||
|
|
||||||
|
# Step 6: Verify services are running
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Step 6: Verifying services...${NC}"
|
||||||
sleep 5
|
sleep 5
|
||||||
|
|
||||||
# Check if servers are running
|
# Check PM2 status
|
||||||
|
echo -e "${YELLOW}PM2 Status:${NC}"
|
||||||
|
pm2 list
|
||||||
|
|
||||||
|
# Check if ports are listening
|
||||||
echo ""
|
echo ""
|
||||||
echo "Checking server status..."
|
echo -e "${YELLOW}Port Status:${NC}"
|
||||||
if lsof -i:3020 > /dev/null 2>&1; then
|
if lsof -i:3020 > /dev/null 2>&1; then
|
||||||
echo "✅ Backend is running on port 3020"
|
echo -e "${GREEN}✓ Backend is running on port 3020${NC}"
|
||||||
else
|
else
|
||||||
echo "❌ Backend failed to start on port 3020"
|
echo -e "${RED}✗ Backend not detected on port 3020${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if lsof -i:3030 > /dev/null 2>&1; then
|
if lsof -i:3030 > /dev/null 2>&1; then
|
||||||
echo "✅ Frontend is running on port 3030"
|
echo -e "${GREEN}✓ Frontend is running on port 3030${NC}"
|
||||||
else
|
else
|
||||||
echo "❌ Frontend failed to start on port 3030"
|
echo -e "${RED}✗ Frontend not detected on port 3030${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check Docker containers
|
||||||
echo ""
|
echo ""
|
||||||
echo "Production servers started!"
|
echo -e "${YELLOW}Docker Containers:${NC}"
|
||||||
echo "Backend: http://localhost:3020"
|
docker ps --filter name=parentflow --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||||||
echo "Frontend: http://localhost:3030"
|
|
||||||
|
# Summary
|
||||||
echo ""
|
echo ""
|
||||||
echo "To check logs:"
|
echo "=========================================="
|
||||||
echo " Backend: tail -f /root/maternal-app/logs/backend-prod.log"
|
echo -e "${GREEN}Production Environment Started!${NC}"
|
||||||
echo " Frontend: tail -f /root/maternal-app/logs/frontend-prod.log"
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Services:"
|
||||||
|
echo " Backend API: http://localhost:3020"
|
||||||
|
echo " Frontend: http://localhost:3030"
|
||||||
|
echo " PostgreSQL: localhost:5432"
|
||||||
|
echo " Redis: localhost:6379"
|
||||||
|
echo " MongoDB: localhost:27017"
|
||||||
|
echo " MinIO: localhost:9000"
|
||||||
|
echo " MinIO Console: localhost:9001"
|
||||||
|
echo ""
|
||||||
|
echo "Management Commands:"
|
||||||
|
echo " PM2 status: pm2 status"
|
||||||
|
echo " PM2 logs: pm2 logs"
|
||||||
|
echo " PM2 restart: pm2 restart all"
|
||||||
|
echo " PM2 stop: pm2 stop all"
|
||||||
|
echo " Docker logs: docker logs parentflow-postgres-prod"
|
||||||
|
echo " Stop all: pm2 stop all && docker-compose -f docker-compose.production.yml down"
|
||||||
|
echo ""
|
||||||
|
echo "Domains (configure in Nginx/DNS):"
|
||||||
|
echo " Frontend: web.parentflowapp.com → localhost:3030"
|
||||||
|
echo " Backend: api.parentflowapp.com → localhost:3020"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}✓ Startup complete!${NC}"
|
||||||
77
stop-production.sh
Executable file
77
stop-production.sh
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ParentFlow Production Stop Script
|
||||||
|
# Stops PM2 processes and Docker containers gracefully
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Color codes
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Stopping ParentFlow Production"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 1: Stop PM2 processes
|
||||||
|
echo -e "${BLUE}Step 1: Stopping PM2 processes...${NC}"
|
||||||
|
if command -v pm2 &> /dev/null; then
|
||||||
|
pm2 stop all 2>/dev/null || true
|
||||||
|
echo -e "${GREEN}✓ PM2 processes stopped${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: PM2 not found${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 2: Stop Docker containers
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Step 2: Stopping Docker containers...${NC}"
|
||||||
|
if docker compose version &> /dev/null; then
|
||||||
|
docker compose -f docker-compose.production.yml down
|
||||||
|
else
|
||||||
|
docker-compose -f docker-compose.production.yml down 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ Docker containers stopped${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: Failed to stop some Docker containers${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify everything is stopped
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Verification:${NC}"
|
||||||
|
|
||||||
|
# Check PM2
|
||||||
|
if command -v pm2 &> /dev/null; then
|
||||||
|
RUNNING_PROCESSES=$(pm2 jlist 2>/dev/null | jq -r '.[] | select(.pm2_env.status == "online") | .name' | wc -l)
|
||||||
|
if [ "$RUNNING_PROCESSES" -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ No PM2 processes running${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: $RUNNING_PROCESSES PM2 processes still running${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Docker
|
||||||
|
RUNNING_CONTAINERS=$(docker ps --filter name=parentflow --format "{{.Names}}" | wc -l)
|
||||||
|
if [ "$RUNNING_CONTAINERS" -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ No ParentFlow Docker containers running${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: $RUNNING_CONTAINERS containers still running${NC}"
|
||||||
|
docker ps --filter name=parentflow
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo -e "${GREEN}Production environment stopped${NC}"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "To completely remove Docker volumes (WARNING: deletes data):"
|
||||||
|
echo " docker-compose -f docker-compose.production.yml down -v"
|
||||||
|
echo ""
|
||||||
|
echo "To remove PM2 processes from startup:"
|
||||||
|
echo " pm2 delete all"
|
||||||
|
echo " pm2 save"
|
||||||
Reference in New Issue
Block a user