deploy
This commit is contained in:
33
Dockerfile
Normal file
33
Dockerfile
Normal file
@@ -0,0 +1,33 @@
|
||||
# Use Node.js 18 LTS
|
||||
FROM node:18-alpine
|
||||
|
||||
# Install MongoDB CLI tools for import operations
|
||||
RUN apk add --no-cache mongodb-tools
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Create uploads directory for images
|
||||
RUN mkdir -p uploads
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:3000/api/health || exit 1
|
||||
|
||||
# Start the application
|
||||
CMD ["npm", "start"]
|
||||
210
README-DEPLOYMENT.md
Normal file
210
README-DEPLOYMENT.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Observation App - Docker Deployment Guide
|
||||
|
||||
This guide provides a complete Docker-based deployment solution for the Observation App with automated database import and image handling.
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
- **observation_app**: Next.js application container
|
||||
- **observation_db**: MongoDB database container
|
||||
- **observation_net**: Private network for container communication
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
- Docker and Docker Compose installed
|
||||
- `.env` file configured
|
||||
- `public/` directory with required files
|
||||
- `public/db/` directory with JSON database files (optional)
|
||||
|
||||
## 🚀 Quick Deployment
|
||||
|
||||
### 1. Prepare Environment
|
||||
|
||||
Ensure you have:
|
||||
```bash
|
||||
# .env file with configuration
|
||||
MONGODB_URI=mongodb://localhost/beanstalk
|
||||
# ... other environment variables
|
||||
|
||||
# public directory structure
|
||||
public/
|
||||
├── observations/ # Image files
|
||||
├── db/ # JSON database files
|
||||
│ ├── indicators.json
|
||||
│ ├── learning_areas.json
|
||||
│ └── observations.json
|
||||
└── ... # Other static files
|
||||
```
|
||||
|
||||
### 2. Deploy
|
||||
|
||||
```bash
|
||||
# Make deployment script executable
|
||||
chmod +x scripts/deploy.sh
|
||||
|
||||
# Run deployment
|
||||
./scripts/deploy.sh
|
||||
```
|
||||
|
||||
The deployment script will:
|
||||
- ✅ Build and start containers
|
||||
- ✅ Wait for database readiness
|
||||
- ✅ Import JSON files from `public/db/` automatically
|
||||
- ✅ Copy images to container
|
||||
- ✅ Perform health checks
|
||||
|
||||
### 3. Access Services
|
||||
|
||||
- **Application**: http://localhost:3000
|
||||
- **Database**: `mongodb://admin:password123@localhost:27017`
|
||||
|
||||
## 🛠️ Management Commands
|
||||
|
||||
### Container Management
|
||||
```bash
|
||||
# View logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Stop services
|
||||
docker-compose down
|
||||
|
||||
# Restart services
|
||||
docker-compose restart
|
||||
|
||||
# Access application container
|
||||
docker-compose exec observation_app sh
|
||||
|
||||
# Access database
|
||||
docker-compose exec observation_db mongosh
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
```bash
|
||||
# Import new JSON file
|
||||
curl -X POST -F "file=@data.json" http://localhost:3000/api/import-json
|
||||
|
||||
# Export database
|
||||
docker-compose exec observation_db mongodump --uri="mongodb://admin:password123@localhost:27017/beanstalk?authSource=admin" --archive > backup.archive
|
||||
```
|
||||
|
||||
## 📁 Data Management
|
||||
|
||||
### Images
|
||||
- Place images in `public/observations/`
|
||||
- Automatically copied to container during deployment
|
||||
- Accessible via `/api/proxy-image` endpoint
|
||||
|
||||
### Database Files
|
||||
- Place JSON files in `public/db/`
|
||||
- Filename becomes collection name (e.g., `users.json` → `users` collection)
|
||||
- Automatically imported during deployment
|
||||
- Existing collections are dropped before import
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables
|
||||
```bash
|
||||
# Database Connection
|
||||
MONGODB_URI=mongodb://admin:password123@observation_db:27017/beanstalk?authSource=admin
|
||||
|
||||
# Application
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
### Docker Compose Settings
|
||||
- **MongoDB Version**: 6.0
|
||||
- **Node.js Version**: 18 Alpine
|
||||
- **Ports**: App (3000), Database (27017)
|
||||
- **Volumes**: Persistent MongoDB data
|
||||
|
||||
## 🔄 Backup & Restore
|
||||
|
||||
### Create Backup
|
||||
```bash
|
||||
chmod +x scripts/backup.sh
|
||||
./scripts/backup.sh
|
||||
```
|
||||
|
||||
Creates backup in `backups/YYYYMMDD_HHMMSS/` with:
|
||||
- MongoDB database archive
|
||||
- Image files
|
||||
- Configuration files
|
||||
- Automated restore script
|
||||
|
||||
### Restore from Backup
|
||||
```bash
|
||||
cd backups/YYYYMMDD_HHMMSS/
|
||||
./restore.sh
|
||||
```
|
||||
|
||||
## 🧹 Cleanup
|
||||
|
||||
### Complete Cleanup
|
||||
```bash
|
||||
chmod +x scripts/cleanup.sh
|
||||
./scripts/cleanup.sh
|
||||
```
|
||||
|
||||
Removes:
|
||||
- All containers
|
||||
- Application images
|
||||
- Unused networks
|
||||
- Optionally: Database volumes (with confirmation)
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Database Connection Issues
|
||||
```bash
|
||||
# Check database status
|
||||
docker-compose exec observation_db mongosh --eval "db.adminCommand('ping')"
|
||||
|
||||
# View database logs
|
||||
docker-compose logs observation_db
|
||||
```
|
||||
|
||||
### Application Issues
|
||||
```bash
|
||||
# Check application health
|
||||
curl http://localhost:3000/api/health
|
||||
|
||||
# View application logs
|
||||
docker-compose logs observation_app
|
||||
```
|
||||
|
||||
### Rebuild Containers
|
||||
```bash
|
||||
# Force rebuild without cache
|
||||
docker-compose build --no-cache
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Health Checks
|
||||
- Application: `/api/health`
|
||||
- Database: MongoDB ping command
|
||||
- Container status: `docker-compose ps`
|
||||
|
||||
### Logs
|
||||
```bash
|
||||
# All services
|
||||
docker-compose logs -f
|
||||
|
||||
# Specific service
|
||||
docker-compose logs -f observation_app
|
||||
docker-compose logs -f observation_db
|
||||
```
|
||||
|
||||
## 🔒 Security Notes
|
||||
|
||||
- Default credentials are for development only
|
||||
- Change MongoDB passwords in production
|
||||
- Use environment variables for sensitive data
|
||||
- Consider using Docker secrets for production
|
||||
|
||||
## 🚀 Production Considerations
|
||||
|
||||
1. **Security**: Update default passwords
|
||||
2. **SSL**: Add HTTPS termination
|
||||
3. **Backup**: Schedule regular backups
|
||||
4. **Monitoring**: Add health monitoring
|
||||
5. **Scaling**: Consider load balancer for multiple app instances
|
||||
45
docker-compose.yml
Normal file
45
docker-compose.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
observation_db:
|
||||
image: mongo:6.0
|
||||
container_name: observation_db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: admin
|
||||
MONGO_INITDB_ROOT_PASSWORD: password123
|
||||
MONGO_INITDB_DATABASE: beanstalk
|
||||
ports:
|
||||
- "27017:27017"
|
||||
volumes:
|
||||
- mongo_data:/data/db
|
||||
- ./scripts/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
|
||||
networks:
|
||||
- observation_net
|
||||
|
||||
observation_app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: observation_app
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- MONGODB_URI=mongodb://admin:password123@observation_db:27017/beanstalk?authSource=admin
|
||||
volumes:
|
||||
- ./public:/app/public:ro
|
||||
- ./uploads:/app/uploads
|
||||
depends_on:
|
||||
- observation_db
|
||||
networks:
|
||||
- observation_net
|
||||
|
||||
volumes:
|
||||
mongo_data:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
observation_net:
|
||||
driver: bridge
|
||||
95
scripts/backup.sh
Executable file
95
scripts/backup.sh
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Backup script for Observation App
|
||||
# This script creates backups of database and images
|
||||
|
||||
set -e
|
||||
|
||||
echo "💾 Creating backup of Observation App data..."
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
# Create backup directory with timestamp
|
||||
BACKUP_DIR="backups/$(date +%Y%m%d_%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
print_status "Backup directory: $BACKUP_DIR"
|
||||
|
||||
# Backup database
|
||||
print_status "Backing up MongoDB database..."
|
||||
docker-compose exec -T observation_db mongodump --uri="mongodb://admin:password123@localhost:27017/beanstalk?authSource=admin" --archive > "$BACKUP_DIR/mongodb_backup.archive"
|
||||
|
||||
# Backup images from public/observations
|
||||
if [ -d "public/observations" ]; then
|
||||
print_status "Backing up images..."
|
||||
cp -r public/observations "$BACKUP_DIR/"
|
||||
print_success "Images backed up"
|
||||
else
|
||||
print_warning "No images directory found"
|
||||
fi
|
||||
|
||||
# Backup configuration files
|
||||
print_status "Backing up configuration..."
|
||||
cp .env "$BACKUP_DIR/" 2>/dev/null || print_warning "No .env file found"
|
||||
cp docker-compose.yml "$BACKUP_DIR/" 2>/dev/null || true
|
||||
|
||||
# Create restore script
|
||||
cat > "$BACKUP_DIR/restore.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Restore script for Observation App backup
|
||||
set -e
|
||||
|
||||
echo "🔄 Restoring Observation App from backup..."
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if containers are running
|
||||
if ! docker-compose ps | grep -q "Up"; then
|
||||
echo "Please start the application first: docker-compose up -d"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Restore database
|
||||
print_status "Restoring database..."
|
||||
docker-compose exec -T observation_db mongorestore --uri="mongodb://admin:password123@localhost:27017/beanstalk?authSource=admin" --archive < mongodb_backup.archive
|
||||
|
||||
# Restore images
|
||||
if [ -d "observations" ]; then
|
||||
print_status "Restoring images..."
|
||||
cp -r observations/* public/observations/
|
||||
print_success "Images restored"
|
||||
fi
|
||||
|
||||
print_success "Restore completed!"
|
||||
EOF
|
||||
|
||||
chmod +x "$BACKUP_DIR/restore.sh"
|
||||
|
||||
print_success "Backup completed successfully!"
|
||||
echo "Backup location: $BACKUP_DIR"
|
||||
echo "To restore: cd $BACKUP_DIR && ./restore.sh"
|
||||
52
scripts/cleanup.sh
Executable file
52
scripts/cleanup.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Cleanup script for Observation App
|
||||
# This script removes all containers, images, and volumes
|
||||
|
||||
set -e
|
||||
|
||||
echo "🧹 Cleaning up Observation App deployment..."
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
# Stop and remove containers
|
||||
print_status "Stopping and removing containers..."
|
||||
docker-compose down -v 2>/dev/null || true
|
||||
|
||||
# Remove images
|
||||
print_status "Removing application images..."
|
||||
docker rmi observation_import-observation_app 2>/dev/null || true
|
||||
|
||||
# Remove unused networks
|
||||
print_status "Removing unused networks..."
|
||||
docker network prune -f 2>/dev/null || true
|
||||
|
||||
# Remove unused volumes (prompt user)
|
||||
read -p "Remove all unused Docker volumes? This will delete database data! (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_status "Removing unused volumes..."
|
||||
docker volume prune -f
|
||||
print_warning "Database data has been removed!"
|
||||
else
|
||||
print_status "Keeping Docker volumes (database data preserved)"
|
||||
fi
|
||||
|
||||
print_success "Cleanup completed!"
|
||||
130
scripts/deploy.sh
Executable file
130
scripts/deploy.sh
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Deployment script for Observation App
|
||||
# This script handles the complete deployment process
|
||||
|
||||
set -e # Exit on any error
|
||||
|
||||
echo "🚀 Starting Observation App Deployment..."
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Check if .env file exists
|
||||
if [ ! -f .env ]; then
|
||||
print_error ".env file not found!"
|
||||
echo "Please create .env file before deploying."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if public directory exists
|
||||
if [ ! -d public ]; then
|
||||
print_error "public directory not found!"
|
||||
echo "Please ensure public directory exists with required files."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if public/db directory exists
|
||||
if [ ! -d public/db ]; then
|
||||
print_warning "public/db directory not found. Creating empty directory..."
|
||||
mkdir -p public/db
|
||||
fi
|
||||
|
||||
# Stop existing containers if running
|
||||
print_status "Stopping existing containers..."
|
||||
docker-compose down 2>/dev/null || true
|
||||
|
||||
# Build and start containers
|
||||
print_status "Building and starting containers..."
|
||||
docker-compose up --build -d
|
||||
|
||||
# Wait for database to be ready
|
||||
print_status "Waiting for database to be ready..."
|
||||
sleep 10
|
||||
|
||||
# Check if database is accessible
|
||||
print_status "Checking database connection..."
|
||||
docker-compose exec observation_db mongosh --eval "db.adminCommand('ping')" > /dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
print_success "Database is ready!"
|
||||
else
|
||||
print_error "Database connection failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Import database if files exist in public/db
|
||||
if [ "$(ls -A public/db/*.json 2>/dev/null)" ]; then
|
||||
print_status "Found database files in public/db. Starting import..."
|
||||
|
||||
# Import each JSON file
|
||||
for file in public/db/*.json; do
|
||||
filename=$(basename "$file" .json)
|
||||
print_status "Importing $filename..."
|
||||
|
||||
# Copy file to container and import
|
||||
docker cp "$file" observation_app:/tmp/"$(basename "$file")"
|
||||
docker-compose exec observation_app curl -X POST -F "file=@/tmp/$(basename "$file")" http://localhost:3000/api/import-json
|
||||
|
||||
# Clean up
|
||||
docker-compose exec observation_app rm "/tmp/$(basename "$file")"
|
||||
|
||||
print_success "Imported $filename"
|
||||
done
|
||||
else
|
||||
print_warning "No database files found in public/db"
|
||||
fi
|
||||
|
||||
# Check application health
|
||||
print_status "Checking application health..."
|
||||
sleep 5
|
||||
if curl -f http://localhost:3000/api/health > /dev/null 2>&1; then
|
||||
print_success "Application is healthy!"
|
||||
else
|
||||
print_warning "Application health check failed, but deployment may still be successful"
|
||||
fi
|
||||
|
||||
# Display deployment information
|
||||
echo ""
|
||||
print_success "🎉 Deployment completed successfully!"
|
||||
echo ""
|
||||
echo "📋 Service Information:"
|
||||
echo " • Application URL: http://localhost:3000"
|
||||
echo " • Database URL: mongodb://admin:password123@localhost:27017"
|
||||
echo " • Database Name: beanstalk"
|
||||
echo ""
|
||||
echo "🔧 Useful Commands:"
|
||||
echo " • View logs: docker-compose logs -f"
|
||||
echo " • Stop services: docker-compose down"
|
||||
echo " • Restart services: docker-compose restart"
|
||||
echo " • Access database: docker-compose exec observation_db mongosh"
|
||||
echo ""
|
||||
echo "📁 Data Locations:"
|
||||
echo " • Images: ./public/observations/ (copied to container)"
|
||||
echo " • Database files: ./public/db/ (imported to MongoDB)"
|
||||
echo " • MongoDB data: Docker volume 'mongo_data'"
|
||||
echo ""
|
||||
|
||||
# Show container status
|
||||
print_status "Container Status:"
|
||||
docker-compose ps
|
||||
18
scripts/init-mongo.js
Normal file
18
scripts/init-mongo.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// MongoDB initialization script
|
||||
// This script runs when the container starts for the first time
|
||||
|
||||
db = db.getSiblingDB('beanstalk');
|
||||
|
||||
// Create application user
|
||||
db.createUser({
|
||||
user: 'app_user',
|
||||
pwd: 'app_password',
|
||||
roles: [
|
||||
{
|
||||
role: 'readWrite',
|
||||
db: 'beanstalk'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
print('Database initialization completed');
|
||||
Reference in New Issue
Block a user