#!/bin/bash # Inventory Management System Docker Build Script # This script builds and deploys the complete inventory solution set -e echo "๐Ÿš€ Building Inventory Management System..." # Docker Compose wrapper function to handle threading errors docker_compose_safe() { local max_attempts=3 local attempt=1 local cmd="$@" while [ $attempt -le $max_attempts ]; do echo "๐Ÿ”„ Docker Compose attempt $attempt/$max_attempts: $cmd" if docker-compose $cmd 2>/dev/null; then echo "โœ… Docker Compose command succeeded" return 0 else echo "โš ๏ธ Docker Compose command failed (attempt $attempt/$max_attempts)" if [ $attempt -eq $max_attempts ]; then echo "๐Ÿ”ง Trying without stderr redirection..." if docker-compose $cmd; then echo "โœ… Docker Compose command succeeded on retry" return 0 else echo "โŒ Docker Compose command failed after $max_attempts attempts" return 1 fi fi sleep 2 ((attempt++)) fi done return 1 } # Load environment variables from .env file if [ -f .env ]; then echo "๐Ÿ“ Loading environment variables from .env..." export $(cat .env | grep -v '^#' | xargs) else echo "โŒ .env file not found. Please copy .env.example to .env and configure it." exit 1 fi # Check if Docker is installed if ! command -v docker &> /dev/null; then echo "โŒ Docker is not installed. Please install Docker first." exit 1 fi # Check if Docker Compose is installed if ! command -v docker-compose &> /dev/null; then echo "โŒ Docker Compose is not installed. Please install Docker Compose first." exit 1 fi # Validate required environment variables if [ -z "$DB_HOST" ] || [ "$DB_HOST" = "your-external-db-host" ]; then echo "โŒ DB_HOST is not configured in .env. Please set your external database host." exit 1 fi if [ -z "$DB_USER" ] || [ "$DB_USER" = "your-db-username" ]; then echo "โŒ DB_USER is not configured in .env. Please set your database username." exit 1 fi if [ -z "$DB_PASS" ] || [ "$DB_PASS" = "your-db-password" ]; then echo "โŒ DB_PASS is not configured in .env. Please set your database password." exit 1 fi # Create uploads and attachments directories if they don't exist if [ ! -d uploads ]; then echo "๐Ÿ“ Creating uploads directory..." mkdir -p uploads chmod 755 uploads fi if [ ! -d attachments ]; then echo "๐Ÿ“ Creating attachments directory..." mkdir -p attachments chmod 755 attachments fi # Copy .env to backend/.env.local for PHP application echo "๐Ÿ“ Copying environment variables to backend/.env.local..." if [ -f .env ]; then cp .env backend/.env.local echo "โœ… Environment variables copied to backend/.env.local" else echo "โŒ .env file not found. Cannot create backend/.env.local" exit 1 fi # Check if Redis is already running on the specified port REDIS_PORT=${REDIS_PORT:-6379} REDIS_RUNNING=false REDIS_HOST="localhost" if command -v netstat &> /dev/null; then if netstat -tuln 2>/dev/null | grep -q ":$REDIS_PORT "; then echo "๐Ÿ”ด Redis is already running on port $REDIS_PORT" REDIS_RUNNING=true REDIS_HOST=$(netstat -tuln 2>/dev/null | grep ":$REDIS_PORT " | head -1 | awk '{print $4}' | cut -d':' -f1) if [ "$REDIS_HOST" = "0.0.0.0" ] || [ "$REDIS_HOST" = "::" ]; then REDIS_HOST="localhost" fi fi elif command -v ss &> /dev/null; then if ss -tuln 2>/dev/null | grep -q ":$REDIS_PORT "; then echo "๐Ÿ”ด Redis is already running on port $REDIS_PORT" REDIS_RUNNING=true REDIS_HOST=$(ss -tuln 2>/dev/null | grep ":$REDIS_PORT " | head -1 | awk '{print $4}' | cut -d':' -f1) if [ "$REDIS_HOST" = "0.0.0.0" ] || [ "$REDIS_HOST" = "::" ]; then REDIS_HOST="localhost" fi fi fi # Display configuration summary echo "๐Ÿ“‹ Configuration Summary:" echo " ๐ŸŒ Frontend Port: ${FRONTEND_PORT:-80}" echo " ๐Ÿ—„๏ธ Database Host: $DB_HOST" echo " ๐Ÿ—„๏ธ Database Port: ${DB_PORT:-3306}" echo " ๐Ÿ—„๏ธ Database Name: ${DB_NAME:-inventory_db}" echo " ๐Ÿ—„๏ธ Database User: $DB_USER" echo " ๐Ÿ”ด Redis Port: $REDIS_PORT ($([ "$REDIS_RUNNING" = true ] && echo "EXTERNAL" || echo "DOCKER"))" echo "" # Test environment variables and database connection inside container echo "๐Ÿงช Testing environment variables and database connection..." docker exec inventory-app php /var/www/html/test-env.php # Fix incorrect image URLs in database echo "๐Ÿ”ง Fixing incorrect image URLs in database..." docker exec inventory-app php /var/www/html/fix_image_urls.php # Run database migration script echo "๐Ÿ”„ Running database migration script..." docker-compose run --rm inventory-app php /var/www/html/migrate.php # Test environment variables and database connectivity echo "๐Ÿ” Testing environment variables and database connectivity..." echo "โ„น๏ธ Note: If you see Docker Compose threading errors, they can be safely ignored" if ! timeout 30 docker-compose run --rm inventory-app php /var/www/html/test-env.php 2>/dev/null; then echo "โŒ Environment variables or database connection test failed." echo "๐Ÿ’ก Make sure:" echo " - Environment variables are properly set in .env" echo " - Database server is running and accessible" echo " - Database '$DB_NAME' exists" echo " - User '$DB_USER' has proper permissions" echo " - Network allows connection from Docker container" echo "" echo "๐Ÿ” Debug: Check container logs for detailed error information" docker-compose logs inventory-app | tail -20 2>/dev/null || echo "Could not fetch logs" exit 1 fi # Build and start the application echo "๐Ÿ”จ Building Docker containers..." echo "โ„น๏ธ Note: Docker Compose threading errors can be safely ignored during build" if [ "$REDIS_RUNNING" = true ]; then echo "๐Ÿ”ด Skipping Redis build (external Redis detected)" docker-compose build inventory-app 2>/dev/null || docker-compose build inventory-app else echo "๐Ÿ”จ Building all containers including Redis..." docker-compose build 2>/dev/null || docker-compose build fi echo "๐Ÿš€ Starting application..." if [ "$REDIS_RUNNING" = true ]; then echo "๐Ÿ”ด Starting application without Redis (using external Redis at $REDIS_HOST:$REDIS_PORT)" docker-compose up -d inventory-app 2>/dev/null || docker-compose up -d inventory-app else echo "๐Ÿš€ Starting application with Redis..." docker-compose up -d 2>/dev/null || docker-compose up -d fi # Wait a moment for services to start echo "โณ Waiting for services to start..." sleep 10 # Check if containers are running echo "๐Ÿ” Checking container status..." docker-compose ps 2>/dev/null || echo "โš ๏ธ Could not get container status (Docker Compose threading error)" # Show logs echo "๐Ÿ“‹ Showing application logs..." docker-compose logs inventory-app 2>/dev/null || echo "โš ๏ธ Could not fetch logs (Docker Compose threading error)" # Clean up unnecessary Docker images echo "๐Ÿงน Cleaning up unnecessary Docker images..." echo "๐Ÿ” Removing dangling images..." DANGLING_IMAGES=$(docker images -f "dangling=true" -q) if [ -n "$DANGLING_IMAGES" ]; then echo "๐Ÿ—‘๏ธ Removing $(echo "$DANGLING_IMAGES" | wc -l) dangling images..." docker rmi $DANGLING_IMAGES 2>/dev/null || true else echo "โœ… No dangling images found" fi echo "๐Ÿ” Removing unused build cache..." docker builder prune -f --keep-storage 1GB 2>/dev/null || true echo "๐Ÿ” Removing unused images (keeping last 24 hours)..." # Remove images older than 24 hours that are not being used UNUSED_IMAGES=$(docker images --format "table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}\t{{.ID}}" | grep -v "REPOSITORY" | awk '$2 < "'$(date -d '24 hours ago' '+%Y-%m-%d %H:%M:%S')'" {print $3}' | head -10) if [ -n "$UNUSED_IMAGES" ]; then echo "๐Ÿ—‘๏ธ Removing old unused images..." echo "$UNUSED_IMAGES" | xargs docker rmi 2>/dev/null || true else echo "โœ… No old unused images found" fi # Show cleanup results echo "" echo "๐Ÿ“Š Docker cleanup summary:" echo " ๐Ÿ“ฆ Images remaining: $(docker images -q | wc -l)" echo " ๐Ÿ’พ Space used: $(docker system df --format "table {{.Type}}\t{{.TotalCount}}\t{{.Size}}" | grep -E "Images|Local Volumes" | awk '{printf " %-15s %3s %10s\n", $1, $2, $3}')" echo "" echo "โœ… Build complete!" echo "" echo "๐ŸŒ Application is available at: http://localhost:${FRONTEND_PORT:-80}" echo "๐Ÿ”ง API endpoints are available at: http://localhost:${FRONTEND_PORT:-80}/api" echo "๐Ÿ—„๏ธ Connected to database: $DB_HOST:${DB_PORT:-3306}/$DB_NAME" if [ "$REDIS_RUNNING" = true ]; then echo "๐Ÿ”ด Using external Redis: $REDIS_HOST:$REDIS_PORT" else echo "๐Ÿ”ด Using Docker Redis: localhost:$REDIS_PORT" fi echo "" echo "๐Ÿ“ Management Commands:" echo " ๐Ÿ›‘ Stop application: docker-compose down" echo " ๐Ÿ“‹ View logs: docker-compose logs -f" echo " ๐Ÿ”„ Rebuild: docker-compose build --no-cache" echo " ๐Ÿš Access container: docker-compose exec inventory-app bash" echo " ๐Ÿงน Full cleanup: docker system prune -a" if [ "$REDIS_RUNNING" = true ]; then echo " ๐Ÿ”ด Redis management: Use your external Redis tools" else echo " ๐Ÿ”ด Redis access: docker-compose exec redis redis-cli" fi