diff --git a/Dockerfile b/Dockerfile index 1285a95..c1c5fa0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use Node.js 18 LTS -FROM node:18-alpine +FROM node:20-alpine # Install MongoDB CLI tools for import operations RUN apk add --no-cache mongodb-tools diff --git a/docker-compose.yml b/docker-compose.yml index 7925abf..cbeeded 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: observation_db: image: mongo:6.0 @@ -10,7 +8,7 @@ services: MONGO_INITDB_ROOT_PASSWORD: password123 MONGO_INITDB_DATABASE: beanstalk ports: - - "27017:27017" + # - "27017:27017" volumes: - mongo_data:/data/db - ./scripts/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro diff --git a/scripts/deploy-docker.sh b/scripts/deploy-docker.sh new file mode 100755 index 0000000..cccae81 --- /dev/null +++ b/scripts/deploy-docker.sh @@ -0,0 +1,171 @@ +#!/bin/bash + +# Deploy Docker App Only - Connects to external MongoDB +# Resource limits: CPU=128, MEMORY=300m + +set -e + +echo "🚀 Deploying Observation App (Docker-only)..." + +# 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" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Configuration +APP_NAME="observation-app" +IMAGE_NAME="observation-app:latest" +CONTAINER_NAME="observation-app-container" +PORT="3000" + +# Resource limits +CPU_LIMIT="128" +MEMORY_LIMIT="300m" + +# Default MongoDB configuration (can be overridden) +MONGODB_URI="${MONGODB_URI:-mongodb://localhost:27017/beanstalk}" + +# Check if .env file exists +if [ ! -f .env ]; then + print_error ".env file not found!" + echo "Please create .env file with MONGODB_URI and other configuration." + exit 1 +fi + +# Load environment variables +source .env + +# Use MONGODB_URI from .env if available +if [ ! -z "$MONGODB_URI" ]; then + MONGODB_URI="$MONGODB_URI" +fi + +print_status "Configuration:" +echo " • MongoDB URI: $MONGODB_URI" +echo " • CPU Limit: $CPU_LIMIT" +echo " • Memory Limit: $MEMORY_LIMIT" +echo " • Port: $PORT" +echo "" + +# Stop and remove existing container +print_status "Stopping existing container..." +docker stop "$CONTAINER_NAME" 2>/dev/null || true +docker rm "$CONTAINER_NAME" 2>/dev/null || true + +# Remove existing image +print_status "Removing existing image..." +docker rmi "$IMAGE_NAME" 2>/dev/null || true + +# Build new image +print_status "Building application image..." +docker build \ + --build-arg NODE_ENV=production \ + -t "$IMAGE_NAME" \ + . + +# Create necessary directories +print_status "Creating directories..." +mkdir -p uploads + +# Run container with resource limits +print_status "Starting container with resource limits..." +docker run -d \ + --name "$CONTAINER_NAME" \ + --cpus="$CPU_LIMIT" \ + --memory="$MEMORY_LIMIT" \ + --memory-swap="$MEMORY_LIMIT" \ + -p "$PORT:3000" \ + -e NODE_ENV=production \ + -e MONGODB_URI="$MONGODB_URI" \ + -v "$(pwd)/public:/app/public:ro" \ + -v "$(pwd)/uploads:/app/uploads" \ + --restart unless-stopped \ + "$IMAGE_NAME" + +# Wait for application to start +print_status "Waiting for application to start..." +sleep 10 + +# Health check +print_status "Performing health check..." +if curl -f "http://localhost:$PORT/api/health" > /dev/null 2>&1; then + print_success "Application is healthy!" +else + print_warning "Health check failed, but container may still be starting..." +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" "$CONTAINER_NAME:/tmp/$(basename "$file")" + docker exec "$CONTAINER_NAME" curl -X POST -F "file=@/tmp/$(basename "$file")" http://localhost:3000/api/import-json + + # Clean up + docker exec "$CONTAINER_NAME" rm "/tmp/$(basename "$file")" + + print_success "Imported $filename" + done +else + print_warning "No database files found in public/db" +fi + +# Display deployment information +echo "" +print_success "🎉 Deployment completed successfully!" +echo "" +echo "📋 Service Information:" +echo " • Application URL: http://localhost:$PORT" +echo " • Container Name: $CONTAINER_NAME" +echo " • Image: $IMAGE_NAME" +echo " • MongoDB: External server ($MONGODB_URI)" +echo "" +echo "🔧 Resource Limits:" +echo " • CPU: $CPU_LIMIT" +echo " • Memory: $MEMORY_LIMIT" +echo " • Memory Swap: $MEMORY_LIMIT" +echo "" +echo "🛠️ Useful Commands:" +echo " • View logs: docker logs -f $CONTAINER_NAME" +echo " • Stop container: docker stop $CONTAINER_NAME" +echo " • Start container: docker start $CONTAINER_NAME" +echo " • Access container: docker exec -it $CONTAINER_NAME sh" +echo " • Resource usage: docker stats $CONTAINER_NAME" +echo "" +echo "📁 Data Locations:" +echo " • Images: ./public/observations/ (mounted read-only)" +echo " • Database files: ./public/db/ (imported to external MongoDB)" +echo " • Uploads: ./uploads/ (mounted for file uploads)" +echo "" + +# Show container status and resource usage +print_status "Container Status:" +docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" + +echo "" +print_status "Resource Usage:" +docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" "$CONTAINER_NAME"