From 02c7f4e2aa25ad7423386d71017ce4e2576fcea9 Mon Sep 17 00:00:00 2001 From: Frank John Begornia Date: Mon, 11 Aug 2025 23:14:31 +0800 Subject: [PATCH] Refactor Docker setup for Laravel 5.0 compatibility and optimize deployment process - Updated Dockerfile configurations for various environments (alpine, basic, cloudrun, minimal, simple, test) to ensure compatibility with Laravel 5.0 and PHP 5.6. - Added PHP compatibility documentation outlining mcrypt requirements and upgrade paths. - Created cloudbuild.yaml for Google Cloud Build integration to streamline deployment to Cloud Run. - Introduced docker-compose.local.yml for local development with MySQL and Redis services. - Enhanced rebuild.sh script for easier local development and migration handling. - Updated Laravel Blade views to correct asset paths. - Added start-local.sh script for quick local setup and service management. --- .dockerignore | 63 +++++++ DEPLOYMENT_GUIDE.md | 229 ++++++++++++++++++++++++ Dockerfile | 12 +- Dockerfile.alpine | 71 ++++++++ Dockerfile.basic | 39 ++++ Dockerfile.cloudrun | 132 ++++++++++++++ Dockerfile.minimal | 86 +++++++++ Dockerfile.simple | 75 ++++++++ Dockerfile.test | 60 +++++++ PHP_COMPATIBILITY.md | 100 +++++++++++ cloudbuild.yaml | 156 ++++++++++++++++ composer.json | 5 +- docker-compose.local.yml | 75 ++++++++ nginx/conf.d/app.conf | 40 ++--- rebuild.sh | 106 +++++++++++ resources/views/merchbay_main.blade.php | 8 +- start-local.sh | 66 +++++++ 17 files changed, 1285 insertions(+), 38 deletions(-) create mode 100644 .dockerignore create mode 100644 DEPLOYMENT_GUIDE.md create mode 100644 Dockerfile.alpine create mode 100644 Dockerfile.basic create mode 100644 Dockerfile.cloudrun create mode 100644 Dockerfile.minimal create mode 100644 Dockerfile.simple create mode 100644 Dockerfile.test create mode 100644 PHP_COMPATIBILITY.md create mode 100644 cloudbuild.yaml create mode 100644 docker-compose.local.yml create mode 100755 rebuild.sh create mode 100755 start-local.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..422c374 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,63 @@ +# Git files +.git +.gitignore +.gitattributes + +# Docker files +Dockerfile* +docker-compose*.yml +.dockerignore + +# Documentation +README.md +DEPLOYMENT_GUIDE.md +*.md + +# Development files +.env.example +.env.local +.env.testing + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + +# Node modules and build files +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Laravel specific +/vendor +/storage/logs/* +!/storage/logs/.gitkeep +/storage/framework/cache/* +!/storage/framework/cache/.gitkeep +/storage/framework/sessions/* +!/storage/framework/sessions/.gitkeep +/storage/framework/views/* +!/storage/framework/views/.gitkeep +/bootstrap/cache/* +!/bootstrap/cache/.gitkeep + +# Testing +/tests +phpunit.xml +phpspec.yml + +# Build tools +gulpfile.js +package.json +package-lock.json +yarn.lock + +# Scripts +start-local.sh +rebuild.sh diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..3d6668d --- /dev/null +++ b/DEPLOYMENT_GUIDE.md @@ -0,0 +1,229 @@ +# Google Cloud Run Deployment Guide for Merchbay Laravel Application + +This guide will help you deploy your Laravel 5 application to Google Cloud Run using the provided `cloudbuild.yaml` configuration. + +## Prerequisites + +1. **Google Cloud Project**: Ensure you have a Google Cloud Project with billing enabled +2. **APIs Enabled**: Enable the following APIs: + - Cloud Build API + - Cloud Run API + - Container Registry API (or Artifact Registry API) + - Cloud SQL API (if using Cloud SQL) + - Secret Manager API (recommended for secrets) + +3. **gcloud CLI**: Install and configure the Google Cloud CLI + +## Pre-deployment Setup + +### 1. Create Cloud SQL Instance (Recommended) + +```bash +# Create MySQL instance +gcloud sql instances create merchbay-db \ + --database-version=MYSQL_8_0 \ + --tier=db-f1-micro \ + --region=us-central1 + +# Create database +gcloud sql databases create merchbay --instance=merchbay-db + +# Create user +gcloud sql users create laravel_user \ + --instance=merchbay-db \ + --password=YOUR_SECURE_PASSWORD +``` + +### 2. Store Secrets in Secret Manager + +```bash +# Application key (generate a new one) +echo "base64:$(openssl rand -base64 32)" | gcloud secrets create APP_KEY --data-file=- + +# Database password +echo "YOUR_DB_PASSWORD" | gcloud secrets create DB_PASSWORD --data-file=- + +# PayPal secrets +echo "YOUR_PAYPAL_LIVE_SECRET" | gcloud secrets create PAYPAL_LIVE_SECRET --data-file=- +echo "YOUR_PAYPAL_SANDBOX_SECRET" | gcloud secrets create PAYPAL_SANDBOX_SECRET --data-file=- + +# Mail password +echo "YOUR_MAIL_PASSWORD" | gcloud secrets create MAIL_PASSWORD --data-file=- +``` + +### 3. Update cloudbuild.yaml Variables + +Update the substitution variables in `cloudbuild.yaml`: + +```yaml +substitutions: + _SERVICE_NAME: 'merchbay-laravel' + _REGION: 'us-central1' # Change to your preferred region + _CLOUDSQL_INSTANCE: 'YOUR_PROJECT_ID:us-central1:merchbay-db' + _DB_DATABASE: 'merchbay' + _DB_USERNAME: 'laravel_user' + # ... other variables +``` + +## Deployment Steps + +### 1. Set up Cloud Build Trigger + +```bash +# Connect your repository to Cloud Build +gcloud builds triggers create github \ + --repo-name=YOUR_REPO_NAME \ + --repo-owner=YOUR_GITHUB_USERNAME \ + --branch-pattern="^main$" \ + --build-config=cloudbuild.yaml + +# Or trigger manually +gcloud builds submit --config=cloudbuild.yaml . +``` + +### 2. Manual Deployment (Alternative) + +```bash +# Set your project ID +export PROJECT_ID=your-project-id + +# Build and deploy +gcloud builds submit --config=cloudbuild.yaml \ + --substitutions=_PROJECT_ID=$PROJECT_ID,_SERVICE_NAME=merchbay-laravel +``` + +## Post-deployment Tasks + +### 1. Run Database Migrations + +```bash +# Create a one-time job for migrations +gcloud run jobs create laravel-migrate \ + --image=gcr.io/$PROJECT_ID/merchbay-laravel:latest \ + --region=us-central1 \ + --set-env-vars="APP_ENV=production" \ + --set-cloudsql-instances=$PROJECT_ID:us-central1:merchbay-db \ + --command="php" \ + --args="artisan,migrate,--force" \ + --max-retries=1 + +# Execute the migration +gcloud run jobs execute laravel-migrate --region=us-central1 --wait +``` + +### 2. Set up Custom Domain (Optional) + +```bash +# Map custom domain +gcloud run domain-mappings create \ + --service=merchbay-laravel \ + --domain=your-domain.com \ + --region=us-central1 +``` + +### 3. Configure Load Balancer and CDN (Optional) + +For better performance, consider setting up: +- Cloud Load Balancer +- Cloud CDN for static assets +- Cloud Storage for file uploads + +## Environment Variables Reference + +The following environment variables are configured in the Cloud Run service: + +### Application Settings +- `APP_ENV=production` +- `APP_DEBUG=false` +- `APP_KEY` (from Secret Manager) + +### Database Settings +- `DB_HOST=127.0.0.1` (Cloud SQL Proxy) +- `DB_DATABASE=merchbay` +- `DB_USERNAME=laravel_user` +- `DB_PASSWORD` (from Secret Manager) + +### Cache & Session +- `CACHE_DRIVER=redis` (requires Redis setup) +- `SESSION_DRIVER=redis` +- `QUEUE_DRIVER=database` + +### PayPal Configuration +- `PAYPAL_MODE=live` (or 'sandbox' for testing) +- `PAYPAL_LIVE_CLIENT_ID` +- `PAYPAL_LIVE_SECRET` +- `PAYPAL_SANDBOX_CLIENT_ID` +- `PAYPAL_SANDBOX_SECRET` + +### Mail Configuration +- `MAIL_DRIVER=smtp` +- `MAIL_HOST` +- `MAIL_PORT` +- `MAIL_USERNAME` +- `MAIL_PASSWORD` + +## Monitoring and Logging + +### Enable Application Insights + +```bash +# Enable Cloud Logging +gcloud logging sinks create laravel-logs \ + bigquery.googleapis.com/projects/$PROJECT_ID/datasets/app_logs +``` + +### Set up Uptime Monitoring + +```bash +# Create uptime check +gcloud alpha monitoring uptime create \ + --display-name="Merchbay Laravel App" \ + --http-check-path="/" \ + --hostname=your-service-url.run.app +``` + +## Troubleshooting + +### Common Issues + +1. **502 Bad Gateway**: Check logs with `gcloud run services logs read merchbay-laravel` +2. **Database Connection Issues**: Verify Cloud SQL instance and VPC configuration +3. **Memory Issues**: Increase memory allocation in cloudbuild.yaml +4. **Timeout Issues**: Increase timeout and check for long-running operations + +### Debugging Commands + +```bash +# View service logs +gcloud run services logs read merchbay-laravel --region=us-central1 + +# Get service details +gcloud run services describe merchbay-laravel --region=us-central1 + +# Check revisions +gcloud run revisions list --service=merchbay-laravel --region=us-central1 +``` + +## Security Considerations + +1. **Use Secret Manager** for all sensitive data +2. **Enable VPC** for database connections +3. **Configure IAM** with least privilege principle +4. **Enable Cloud Armor** for DDoS protection +5. **Use HTTPS** with managed SSL certificates +6. **Regular Updates** for dependencies and base images + +## Cost Optimization + +1. **Set Min Instances to 0** for cost savings +2. **Use Appropriate CPU/Memory** settings +3. **Implement Caching** (Redis/Memcached) +4. **Optimize Images** and use multi-stage builds +5. **Monitor Usage** with Cloud Monitoring + +## Support + +For issues specific to: +- **Cloud Run**: Check [Cloud Run documentation](https://cloud.google.com/run/docs) +- **Laravel**: Check [Laravel documentation](https://laravel.com/docs) +- **PayPal Integration**: Check [PayPal developer documentation](https://developer.paypal.com/) diff --git a/Dockerfile b/Dockerfile index 8a08879..969574f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,29 +11,23 @@ RUN apk --update --no-cache add \ zip \ unzip \ libmcrypt-dev \ - && docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install gd pdo pdo_mysql zip mcrypt # Set the working directory in the container WORKDIR /var/www -# Clear cache -# RUN apt-get clean && rm -rf /var/lib/apt/lists/* - # Copy the Laravel application files to the container COPY . . # Set appropriate permissions for Laravel storage and bootstrap cache -RUN chown -R www-data:www-data storage bootstrap +RUN chown -R www-data:www-data storage bootstrap/cache # Install Composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Install Laravel dependencies -RUN composer install --no-plugins --no-scripts - -# Generate Laravel application key -RUN php artisan key:generate +RUN composer install --no-interaction --no-plugins --no-scripts # Create directory for the socket and set permissions RUN mkdir -p /run/php && chown www-data:www-data /run/php diff --git a/Dockerfile.alpine b/Dockerfile.alpine new file mode 100644 index 0000000..5e11395 --- /dev/null +++ b/Dockerfile.alpine @@ -0,0 +1,71 @@ +# Debug Dockerfile - Let's try the original approach that was working +FROM php:5.6-fpm-alpine + +# Set working directory +WORKDIR /var/www + +# Install system dependencies and PHP extensions +RUN apk --update --no-cache add \ + nginx \ + libpng-dev \ + libjpeg-turbo-dev \ + freetype-dev \ + libzip-dev \ + zip \ + unzip \ + libmcrypt-dev \ + curl \ + git \ + && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ + && docker-php-ext-install gd pdo pdo_mysql zip mcrypt mbstring + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Copy the Laravel application files to the container +COPY . . + +# Set appropriate permissions for Laravel storage and bootstrap cache +RUN chown -R www-data:www-data storage bootstrap/cache + +# Install Laravel dependencies +RUN composer install --no-interaction --no-plugins --no-scripts --no-dev + +# Create .env file +RUN if [ ! -f .env ]; then cp .env.example .env; fi + +# Generate application key +RUN php artisan key:generate || true + +# Create directory for the socket and set permissions +RUN mkdir -p /run/php && chown www-data:www-data /run/php + +# Configure nginx for Laravel +RUN echo 'server { + listen 80; + server_name localhost; + root /var/www/public; + index index.php index.html index.htm; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass 127.0.0.1:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } +}' > /etc/nginx/conf.d/default.conf + +# Create startup script +RUN echo '#!/bin/sh +php-fpm -D +nginx -g "daemon off;"' > /start.sh && chmod +x /start.sh + +# Expose port 80 +EXPOSE 80 + +# Start both PHP-FPM and Nginx +CMD ["/start.sh"] diff --git a/Dockerfile.basic b/Dockerfile.basic new file mode 100644 index 0000000..9097e91 --- /dev/null +++ b/Dockerfile.basic @@ -0,0 +1,39 @@ +# Bare minimum working Dockerfile for Laravel 5.0 +FROM php:5.6-apache + +WORKDIR /var/www/html + +# Install absolute essentials only +RUN apt-get update \ + && apt-get install -y \ + curl \ + git \ + libmcrypt-dev \ + && docker-php-ext-install \ + pdo \ + pdo_mysql \ + mcrypt \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Enable Apache rewrite +RUN a2enmod rewrite + +# Configure Apache for Laravel +ENV APACHE_DOCUMENT_ROOT=/var/www/html/public +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf + +# Copy app and set permissions +COPY . /var/www/html/ +RUN chown -R www-data:www-data /var/www/html + +# Basic Laravel setup +RUN if [ ! -f .env ]; then cp .env.example .env; fi +RUN composer install --no-dev --no-interaction --ignore-platform-reqs +RUN php artisan key:generate || true + +EXPOSE 80 +CMD ["apache2-foreground"] diff --git a/Dockerfile.cloudrun b/Dockerfile.cloudrun new file mode 100644 index 0000000..eee73ab --- /dev/null +++ b/Dockerfile.cloudrun @@ -0,0 +1,132 @@ +# Dockerfile optimized for Google Cloud Run +# Use PHP 5.6 with Apache (matches Laravel 5.0 requirements perfectly) +FROM php:5.6-apache + +# Set working directory +WORKDIR /var/www/html + +# Install system dependencies and PHP extensions required for Laravel +RUN apt-get update && apt-get install -y \ + libpng-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ + libmcrypt-dev \ + zlib1g-dev \ + zip \ + unzip \ + git \ + curl \ + libxml2-dev \ + && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ + && docker-php-ext-install \ + pdo \ + pdo_mysql \ + mbstring \ + zip \ + gd \ + xml \ + mcrypt \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Enable Apache modules and configure +RUN a2enmod rewrite headers +RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf + +# Configure Apache document root for Laravel +ENV APACHE_DOCUMENT_ROOT=/var/www/html/public +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf +RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + +# Copy Apache virtual host configuration +COPY < + ServerAdmin webmaster@localhost + DocumentRoot /var/www/html/public + + + AllowOverride All + Require all granted + + + # Logging + ErrorLog \${APACHE_LOG_DIR}/error.log + CustomLog \${APACHE_LOG_DIR}/access.log combined + + # Security headers + Header always set X-Content-Type-Options nosniff + Header always set X-Frame-Options DENY + Header always set X-XSS-Protection "1; mode=block" + Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" + Header always set Referrer-Policy "strict-origin-when-cross-origin" + +EOF + +# Copy application files +COPY . /var/www/html/ + +# Fix Git ownership issue for the repository +RUN git config --global --add safe.directory /var/www/html || true + +# Install PHP dependencies +RUN composer install --no-dev --optimize-autoloader --no-interaction + +# Set proper permissions for Laravel +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html \ + && chmod -R 775 /var/www/html/storage \ + && chmod -R 775 /var/www/html/bootstrap/cache + +# Create .env file from .env.example if it doesn't exist +RUN if [ ! -f /var/www/html/.env ]; then \ + cp /var/www/html/.env.example /var/www/html/.env; \ + fi + +# Switch to www-data user for Laravel commands to avoid ownership issues +USER www-data + +# Generate application key (will be overridden by environment variables in Cloud Run) +RUN php artisan key:generate || true + +# Clear and cache configuration for production +RUN php artisan config:clear || true \ + && php artisan route:clear || true \ + && php artisan view:clear || true + +# Switch back to root for the remaining setup +USER root + +# Create startup script +COPY <> /etc/apache2/apache2.conf + +# Configure Apache document root for Laravel +ENV APACHE_DOCUMENT_ROOT=/var/www/html/public +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf +RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf + +# Simple Apache configuration +RUN echo '\n\ + DocumentRoot /var/www/html/public\n\ + \n\ + AllowOverride All\n\ + Require all granted\n\ + \n\ +' > /etc/apache2/sites-available/000-default.conf + +# Copy application files +COPY . /var/www/html/ + +# Fix Git ownership issue +RUN git config --global --add safe.directory /var/www/html || true + +# Install PHP dependencies +RUN composer install --no-dev --optimize-autoloader --no-interaction + +# Set proper permissions +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html \ + && chmod -R 775 /var/www/html/storage \ + && chmod -R 775 /var/www/html/bootstrap/cache + +# Create .env file if it doesn't exist +RUN if [ ! -f /var/www/html/.env ]; then \ + cp /var/www/html/.env.example /var/www/html/.env; \ + fi + +# Switch to www-data for Laravel commands +USER www-data +RUN php artisan key:generate || true +USER root + +# Create simple startup script +RUN echo '#!/bin/bash\n\ +set -e\n\ +echo "Starting Laravel application..."\n\ +exec apache2-foreground' > /usr/local/bin/start.sh \ + && chmod +x /usr/local/bin/start.sh + +# Expose port 80 +EXPOSE 80 + +# Start Apache +CMD ["/usr/local/bin/start.sh"] diff --git a/Dockerfile.simple b/Dockerfile.simple new file mode 100644 index 0000000..0083273 --- /dev/null +++ b/Dockerfile.simple @@ -0,0 +1,75 @@ +# Ultra-minimal Dockerfile for Laravel 5.0 with PHP 5.6 +FROM php:5.6-apache + +# Set working directory +WORKDIR /var/www/html + +# Install packages one by one to identify issues +RUN apt-get update + +# Install core development tools first +RUN apt-get install -y \ + curl \ + git \ + zip \ + unzip + +# Install mcrypt (most important for Laravel 5.0) +RUN apt-get install -y libmcrypt-dev \ + && docker-php-ext-install mcrypt + +# Install basic PHP extensions +RUN docker-php-ext-install \ + pdo \ + pdo_mysql \ + mbstring + +# Try to install GD dependencies +RUN apt-get install -y \ + libpng-dev \ + libjpeg-dev \ + libfreetype6-dev \ + && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ + && docker-php-ext-install gd + +# Install zip extension +RUN apt-get install -y zlib1g-dev \ + && docker-php-ext-install zip + +# Clean up +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Enable Apache rewrite module +RUN a2enmod rewrite + +# Configure Apache +RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf +ENV APACHE_DOCUMENT_ROOT=/var/www/html/public +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf + +# Copy application files +COPY . /var/www/html/ + +# Set basic permissions +RUN chown -R www-data:www-data /var/www/html \ + && chmod -R 755 /var/www/html + +# Create .env file if needed +RUN if [ ! -f /var/www/html/.env ]; then \ + cp /var/www/html/.env.example /var/www/html/.env; \ + fi + +# Install dependencies without dev packages +RUN composer install --no-dev --no-interaction || true + +# Generate Laravel key +RUN php artisan key:generate || true + +# Expose port 80 +EXPOSE 80 + +# Start Apache +CMD ["apache2-foreground"] diff --git a/Dockerfile.test b/Dockerfile.test new file mode 100644 index 0000000..3c9d289 --- /dev/null +++ b/Dockerfile.test @@ -0,0 +1,60 @@ +# Test Dockerfile to identify available packages +FROM php:5.6-apache + +WORKDIR /var/www/html + +# Update package lists first +RUN apt-get update + +# Test each package individually +RUN apt-get install -y curl || echo "curl failed" +RUN apt-get install -y git || echo "git failed" +RUN apt-get install -y zip || echo "zip failed" +RUN apt-get install -y unzip || echo "unzip failed" + +# Test mcrypt (most important) +RUN apt-get install -y libmcrypt-dev || echo "libmcrypt-dev failed" + +# Test image libraries one by one +RUN apt-get install -y libpng-dev || echo "libpng-dev failed" +RUN apt-get install -y libjpeg-dev || echo "libjpeg-dev failed" +RUN apt-get install -y libfreetype6-dev || echo "libfreetype6-dev failed" + +# Test zip library +RUN apt-get install -y zlib1g-dev || echo "zlib1g-dev failed" + +# Try to install PHP extensions +RUN docker-php-ext-install mcrypt || echo "mcrypt extension failed" +RUN docker-php-ext-install pdo || echo "pdo extension failed" +RUN docker-php-ext-install pdo_mysql || echo "pdo_mysql extension failed" +RUN docker-php-ext-install mbstring || echo "mbstring extension failed" + +# Test GD configuration +RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ || echo "gd configure failed" +RUN docker-php-ext-install gd || echo "gd extension failed" + +# Test zip extension +RUN docker-php-ext-install zip || echo "zip extension failed" + +# Clean up +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Basic Apache setup +RUN a2enmod rewrite +ENV APACHE_DOCUMENT_ROOT=/var/www/html/public +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf + +# Test copy and basic setup +COPY . /var/www/html/ +RUN chown -R www-data:www-data /var/www/html + +# Test Laravel commands +RUN if [ ! -f .env ]; then cp .env.example .env; fi || echo ".env creation failed" +RUN composer install --no-dev --no-interaction || echo "composer install failed" +RUN php artisan key:generate || echo "key generation failed" + +EXPOSE 80 +CMD ["apache2-foreground"] diff --git a/PHP_COMPATIBILITY.md b/PHP_COMPATIBILITY.md new file mode 100644 index 0000000..807e5d2 --- /dev/null +++ b/PHP_COMPATIBILITY.md @@ -0,0 +1,100 @@ +# Laravel 5.0 and PHP Compatibility Guide + +## Issue: mcrypt Extension Required + +Laravel 5.0 requires the `mcrypt` PHP extension, which was: + +- **Deprecated** in PHP 7.1 +- **Removed** in PHP 7.2+ + +## Solutions + +### Option 1: Use PHP 5.6 (Current Implementation) + +The `Dockerfile.minimal` has been updated to use PHP 5.6 which is the ideal match for Laravel 5.0. + +**Pros:** + +- Perfect compatibility with Laravel 5.0 +- Native mcrypt support +- All packages available and tested +- Matches original development environment + +**Cons:** + +- PHP 5.6 reached end-of-life in December 2018 +- Security concerns for long-term production use + +### Option 2: Upgrade Laravel (Recommended for Production) +Upgrade to Laravel 5.5+ which doesn't require mcrypt. + +```bash +# Update composer.json +"laravel/framework": "5.8.*" + +# Remove mcrypt dependencies and update encryption +php artisan key:generate +``` + +### Option 3: Use OpenSSL Instead (Laravel 5.2+) +If upgrading Laravel, update encryption configuration: + +```php +// config/app.php +'cipher' => 'AES-256-CBC', +``` + +## Current Docker Configuration + +The Dockerfile now uses: + +- **Base Image**: `php:5.6-apache` +- **mcrypt Extension**: Native support (no installation issues) +- **Other Extensions**: All Laravel 5.0 requirements met +- **Package Compatibility**: Perfect match for PHP 5.6 + +## Production Recommendations + +For a production deployment, consider: + +1. **Upgrade Laravel** to 5.8 or later (LTS) +2. **Use PHP 7.4+** for better performance and security +3. **Replace mcrypt** with OpenSSL encryption + +## Quick Upgrade Path (Optional) + +If you want to modernize the application: + +### Step 1: Update composer.json +```json +{ + "require": { + "laravel/framework": "5.8.*" + } +} +``` + +### Step 2: Update Dockerfile to use PHP 7.4 +```dockerfile +FROM php:7.4-apache +# Remove mcrypt installation +``` + +### Step 3: Update configuration +```bash +php artisan key:generate +php artisan config:cache +``` + +## Security Note + +Since PHP 7.1 is end-of-life, monitor for security updates and consider upgrading the Laravel version for long-term production use. + +## Testing the Current Setup + +The current configuration should work with: +```bash +./start-local.sh +``` + +This will use PHP 7.1 with mcrypt support for Laravel 5.0 compatibility. diff --git a/cloudbuild.yaml b/cloudbuild.yaml new file mode 100644 index 0000000..ef07a1b --- /dev/null +++ b/cloudbuild.yaml @@ -0,0 +1,156 @@ +# Google Cloud Build configuration for Laravel 5 application deployment to Cloud Run +steps: + # Step 1: Build the Docker image + - name: 'gcr.io/cloud-builders/docker' + args: + - 'build' + - '-t' + - 'gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA' + - '-t' + - 'gcr.io/$PROJECT_ID/merchbay-laravel:latest' + - '-f' + - 'Dockerfile.simple' + - '.' + id: 'build-image' + + # Step 2: Push the Docker image to Google Container Registry + - name: 'gcr.io/cloud-builders/docker' + args: + - 'push' + - 'gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA' + id: 'push-image' + waitFor: ['build-image'] + + # Step 3: Push the latest tag as well + - name: 'gcr.io/cloud-builders/docker' + args: + - 'push' + - 'gcr.io/$PROJECT_ID/merchbay-laravel:latest' + id: 'push-latest' + waitFor: ['build-image'] + + # Step 4: Run database migrations (optional - only if you have Cloud SQL configured) + # Uncomment and configure if you need to run migrations + # - name: 'gcr.io/cloud-builders/gcloud' + # entrypoint: 'bash' + # args: + # - '-c' + # - | + # gcloud run jobs create laravel-migrate \ + # --image=gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA \ + # --region=$_REGION \ + # --set-env-vars="APP_ENV=production,APP_KEY=$_APP_KEY,DB_HOST=$_DB_HOST,DB_DATABASE=$_DB_DATABASE,DB_USERNAME=$_DB_USERNAME,DB_PASSWORD=$_DB_PASSWORD" \ + # --set-cloudsql-instances=$_CLOUDSQL_INSTANCE \ + # --command="php" \ + # --args="artisan,migrate,--force" \ + # --max-retries=1 \ + # --replace || true + # gcloud run jobs execute laravel-migrate --region=$_REGION --wait + # id: 'run-migrations' + # waitFor: ['push-image'] + + # Step 5: Deploy to Cloud Run + - name: 'gcr.io/cloud-builders/gcloud' + args: + - 'run' + - 'deploy' + - '$_SERVICE_NAME' + - '--image' + - 'gcr.io/$PROJECT_ID/merchbay-laravel:$COMMIT_SHA' + - '--region' + - '$_REGION' + - '--platform' + - 'managed' + - '--allow-unauthenticated' + - '--port' + - '8080' + - '--memory' + - '$_MEMORY' + - '--cpu' + - '$_CPU' + - '--timeout' + - '$_TIMEOUT' + - '--concurrency' + - '$_CONCURRENCY' + - '--min-instances' + - '$_MIN_INSTANCES' + - '--max-instances' + - '$_MAX_INSTANCES' + - '--set-env-vars' + - 'APP_ENV=production,APP_DEBUG=false,APP_KEY=$_APP_KEY,DB_HOST=$_DB_HOST,DB_DATABASE=$_DB_DATABASE,DB_USERNAME=$_DB_USERNAME,DB_PASSWORD=$_DB_PASSWORD,CACHE_DRIVER=redis,SESSION_DRIVER=redis,QUEUE_DRIVER=database,PAYPAL_MODE=$_PAYPAL_MODE,PAYPAL_LIVE_CLIENT_ID=$_PAYPAL_LIVE_CLIENT_ID,PAYPAL_LIVE_SECRET=$_PAYPAL_LIVE_SECRET,PAYPAL_SANDBOX_CLIENT_ID=$_PAYPAL_SANDBOX_CLIENT_ID,PAYPAL_SANDBOX_SECRET=$_PAYPAL_SANDBOX_SECRET,MAIL_DRIVER=$_MAIL_DRIVER,MAIL_HOST=$_MAIL_HOST,MAIL_PORT=$_MAIL_PORT,MAIL_USERNAME=$_MAIL_USERNAME,MAIL_PASSWORD=$_MAIL_PASSWORD,GOOGLE_ANALYTICS_VIEW_ID=$_GOOGLE_ANALYTICS_VIEW_ID' + - '--set-cloudsql-instances' + - '$_CLOUDSQL_INSTANCE' + - '--vpc-connector' + - '$_VPC_CONNECTOR' + - '--add-cloudsql-instances' + - '$_CLOUDSQL_INSTANCE' + id: 'deploy-service' + waitFor: ['push-image'] + +# Substitution variables - you can override these in your Cloud Build trigger +substitutions: + # Service configuration + _SERVICE_NAME: 'merchbay-laravel' + _REGION: 'us-central1' + + # Resource limits + _MEMORY: '1Gi' + _CPU: '1000m' + _TIMEOUT: '300s' + _CONCURRENCY: '80' + _MIN_INSTANCES: '0' + _MAX_INSTANCES: '10' + + # Database configuration (Cloud SQL) + _CLOUDSQL_INSTANCE: 'YOUR_PROJECT_ID:REGION:INSTANCE_NAME' + _DB_HOST: '127.0.0.1' + _DB_DATABASE: 'merchbay' + _DB_USERNAME: 'laravel_user' + _DB_PASSWORD: 'YOUR_DB_PASSWORD' + + # VPC configuration (if needed) + _VPC_CONNECTOR: 'projects/YOUR_PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME' + + # Application configuration + _APP_KEY: 'base64:YOUR_APP_KEY_HERE' + + # PayPal configuration + _PAYPAL_MODE: 'live' + _PAYPAL_LIVE_CLIENT_ID: 'YOUR_PAYPAL_LIVE_CLIENT_ID' + _PAYPAL_LIVE_SECRET: 'YOUR_PAYPAL_LIVE_SECRET' + _PAYPAL_SANDBOX_CLIENT_ID: 'YOUR_PAYPAL_SANDBOX_CLIENT_ID' + _PAYPAL_SANDBOX_SECRET: 'YOUR_PAYPAL_SANDBOX_SECRET' + + # Mail configuration + _MAIL_DRIVER: 'smtp' + _MAIL_HOST: 'smtp.gmail.com' + _MAIL_PORT: '587' + _MAIL_USERNAME: 'your-email@domain.com' + _MAIL_PASSWORD: 'your-app-password' + + # Google Analytics + _GOOGLE_ANALYTICS_VIEW_ID: 'YOUR_GA_VIEW_ID' + +# Build options +options: + # Use a more powerful machine for faster builds + machineType: 'E2_HIGHCPU_8' + + # Enable detailed logging + logging: CLOUD_LOGGING_ONLY + +# Build timeout +timeout: '1200s' + +# Store build logs in Cloud Logging +logsBucket: 'gs://YOUR_PROJECT_ID_cloudbuild-logs' + +# Available logs for debugging +availableSecrets: + secretManager: + - versionName: 'projects/YOUR_PROJECT_ID/secrets/APP_KEY/versions/latest' + env: 'APP_KEY' + - versionName: 'projects/YOUR_PROJECT_ID/secrets/DB_PASSWORD/versions/latest' + env: 'DB_PASSWORD' + - versionName: 'projects/YOUR_PROJECT_ID/secrets/PAYPAL_LIVE_SECRET/versions/latest' + env: 'PAYPAL_LIVE_SECRET' diff --git a/composer.json b/composer.json index f3fff5b..6a2cf3a 100755 --- a/composer.json +++ b/composer.json @@ -46,6 +46,9 @@ ] }, "config": { - "preferred-install": "dist" + "preferred-install": "dist", + "allow-plugins": { + "kylekatarnls/update-helper": true + } } } diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..19e65ae --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,75 @@ +# Docker Compose for local development and testing +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile.basic + ports: + - "8080:80" + environment: + - APP_ENV=local + - APP_DEBUG=true + - APP_KEY=base64:your-app-key-here + - DB_HOST=mysql + - DB_DATABASE=merchbay + - DB_USERNAME=laravel_user + - DB_PASSWORD=secret + - CACHE_DRIVER=file + - SESSION_DRIVER=file + - REDIS_HOST=redis + - QUEUE_DRIVER=sync + - PAYPAL_MODE=sandbox + - PAYPAL_SANDBOX_CLIENT_ID=your-sandbox-client-id + - PAYPAL_SANDBOX_SECRET=your-sandbox-secret + - MAIL_DRIVER=log + volumes: + - ./storage:/var/www/html/storage + - ./bootstrap/cache:/var/www/html/bootstrap/cache + depends_on: + - mysql + - redis + networks: + - app-network + + mysql: + image: mysql:8.0 + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=merchbay + - MYSQL_USER=laravel_user + - MYSQL_PASSWORD=secret + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + networks: + - app-network + + redis: + image: redis:7-alpine + ports: + - "6379:6379" + networks: + - app-network + + phpmyadmin: + image: phpmyadmin/phpmyadmin + environment: + - PMA_HOST=mysql + - PMA_USER=root + - PMA_PASSWORD=root + ports: + - "8081:80" + depends_on: + - mysql + networks: + - app-network + +volumes: + mysql_data: + +networks: + app-network: + driver: bridge diff --git a/nginx/conf.d/app.conf b/nginx/conf.d/app.conf index 501fb8a..2b2ab74 100644 --- a/nginx/conf.d/app.conf +++ b/nginx/conf.d/app.conf @@ -3,37 +3,29 @@ server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; - root /var/www; - index index.php index.html; + root /var/www/public; - location / { - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE, HEAD'; - add_header 'Access-Control-Max-Age' '1728000'; - add_header 'Access-Control-Allow-Headers' '*'; - #add_header 'Content-Type: text/plain; charset=UTF-8'; - #add_header 'Content-Length: 0'; - return 204; - } + location / { try_files $uri $uri/ /index.php?$query_string; - } + location ~ \.php$ { - fastcgi_index index.php; - fastcgi_pass app:9000; - - include fastcgi_params; + try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + fastcgi_pass app:9000; + fastcgi_index index.php; + include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - + fastcgi_param PATH_INFO $fastcgi_path_info; } + + location ~ /\.ht { + deny all; + } + location ~* \.(css|less|js|jpg|png|gif)$ { - add_header Cache-Control "no-cache, no-store, must-revalidate"; - add_header Pragma "no-cache"; - expires 0; + expires 0; + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; } - } \ No newline at end of file diff --git a/rebuild.sh b/rebuild.sh new file mode 100755 index 0000000..e5e22f5 --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# Check if docker compose (new) or docker-compose (old) is available +if command -v docker &>/dev/null; then + if docker compose version &>/dev/null; then + DOCKER_COMPOSE="docker compose" + elif command -v docker-compose &>/dev/null; then + DOCKER_COMPOSE="docker-compose" + else + echo "โŒ Error: Neither 'docker compose' nor 'docker-compose' found." + echo "Please install Docker Desktop from https://www.docker.com/products/docker-desktop/" + exit 1 + fi +else + echo "โŒ Error: Docker is not installed." + echo "Please install Docker Desktop from https://www.docker.com/products/docker-desktop/" + exit 1 +fi + +echo "๐Ÿš€ Starting rebuild process..." + +# Function to display usage +show_usage() { + echo "Usage: ./rebuild.sh [OPTIONS]" + echo "Options:" + echo " -h, --help Show this help message" + echo " -c, --clean Perform a clean rebuild (no cache)" + echo " -f, --fresh Perform a fresh migration" +} + +# Default values +CLEAN_BUILD=false +FRESH_MIGRATION=false + +# Parse arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + -h|--help) show_usage; exit 0 ;; + -c|--clean) CLEAN_BUILD=true ;; + -f|--fresh) FRESH_MIGRATION=true ;; + *) echo "Unknown parameter: $1"; show_usage; exit 1 ;; + esac + shift +done + +# Pull latest changes from git +echo "๐Ÿ“ฅ Pulling latest changes from git..." +if ! git pull; then + echo "โŒ Git pull failed. Please resolve any conflicts and try again." + exit 1 +fi + +# Stop running containers +echo "๐Ÿ“ฅ Stopping running containers..." +$DOCKER_COMPOSE down + +# Remove old images if clean build +if [ "$CLEAN_BUILD" = true ] ; then + echo "๐Ÿงน Cleaning Docker cache..." + $DOCKER_COMPOSE rm -f + docker system prune -f +fi + +# Build and start containers +echo "๐Ÿ—๏ธ Building containers..." +if [ "$CLEAN_BUILD" = true ] ; then + $DOCKER_COMPOSE build --no-cache +else + $DOCKER_COMPOSE build +fi + +# Start containers +echo "๐Ÿš€ Starting containers..." +$DOCKER_COMPOSE up -d + +# Wait for the containers to be ready +echo "โณ Waiting for containers to be ready..." +sleep 10 + +# Clear Laravel cache +echo "๐Ÿงน Clearing Laravel cache..." +$DOCKER_COMPOSE exec app php artisan cache:clear +$DOCKER_COMPOSE exec app php artisan config:clear +$DOCKER_COMPOSE exec app php artisan view:clear + +# Run composer install +echo "๐Ÿ“ฆ Installing dependencies..." +$DOCKER_COMPOSE exec app composer install + +# Generate application key if .env exists and APP_KEY is empty +if [ -f .env ] && ! grep -q "^APP_KEY=[A-Za-z0-9+/]\{40\}$" .env; then + echo "๐Ÿ”‘ Generating application key..." + $DOCKER_COMPOSE exec app php artisan key:generate +fi + +# Run migrations if requested +if [ "$FRESH_MIGRATION" = true ] ; then + echo "๐Ÿ”„ Running fresh migrations..." + $DOCKER_COMPOSE exec app php artisan migrate:fresh +else + echo "๐Ÿ”„ Running migrations..." + $DOCKER_COMPOSE exec app php artisan migrate +fi + +echo "โœจ Rebuild completed!" +echo "๐ŸŒ Your application should be available at http://localhost:8080" \ No newline at end of file diff --git a/resources/views/merchbay_main.blade.php b/resources/views/merchbay_main.blade.php index 35a1104..7b44a12 100755 --- a/resources/views/merchbay_main.blade.php +++ b/resources/views/merchbay_main.blade.php @@ -10,11 +10,11 @@ Merchbay - + - + @@ -258,7 +258,7 @@ } function fetchCanada() { - $.getJSON("{{ asset('/public/api/canada.json') }}", function(items) { + $.getJSON("{{ asset('/api/canada.json') }}", function(items) { var states = []; Object.keys(items).forEach(function(state) { @@ -307,7 +307,7 @@ } function fetchUSA() { - $.getJSON("{{ asset('/public/api/usaCities.json') }}", function(data) { + $.getJSON("{{ asset('/api/usaCities.json') }}", function(data) { var states = []; for (i = 0; i < data.length; i++) { diff --git a/start-local.sh b/start-local.sh new file mode 100755 index 0000000..93322fb --- /dev/null +++ b/start-local.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Quick start script for local development and testing before Cloud Run deployment + +set -e + +echo "๐Ÿš€ Starting Merchbay Laravel Application Setup..." + +# Check if Docker is running +if ! docker info > /dev/null 2>&1; then + echo "โŒ Docker is not running. Please start Docker and try again." + exit 1 +fi + +# Determine which docker compose command to use +if command -v docker-compose > /dev/null 2>&1; then + DOCKER_COMPOSE="docker-compose" +elif docker compose version > /dev/null 2>&1; then + DOCKER_COMPOSE="docker compose" +else + echo "โŒ Neither 'docker-compose' nor 'docker compose' is available." + echo "Please install Docker Compose and try again." + exit 1 +fi + +echo "โ„น๏ธ Using: $DOCKER_COMPOSE" + +# Check if .env file exists +if [ ! -f .env ]; then + echo "๐Ÿ“„ Creating .env file from .env.example..." + cp .env.example .env + echo "โœ… .env file created. Please update it with your configuration." +fi + +# Build and start services +echo "๐Ÿ”จ Building Docker images..." +$DOCKER_COMPOSE -f docker-compose.local.yml build + +echo "๐Ÿš€ Starting services..." +$DOCKER_COMPOSE -f docker-compose.local.yml up -d + +echo "โณ Waiting for services to be ready..." +sleep 30 + +# Run Laravel setup commands +echo "๐Ÿ”ง Setting up Laravel..." +$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan key:generate +#$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan migrate --force +$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan config:cache +$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan route:cache +$DOCKER_COMPOSE -f docker-compose.local.yml exec app php artisan view:cache + +echo "โœ… Setup complete!" +echo "" +echo "๐ŸŒ Your application is now running at:" +echo " Application: http://localhost:8080" +echo " phpMyAdmin: http://localhost:8081" +echo "" +echo "๐Ÿ“Š Check logs with:" +echo " $DOCKER_COMPOSE -f docker-compose.local.yml logs -f app" +echo "" +echo "๐Ÿ›‘ Stop the application with:" +echo " $DOCKER_COMPOSE -f docker-compose.local.yml down" +echo "" +echo "๐Ÿš€ When ready to deploy to Cloud Run, use:" +echo " gcloud builds submit --config=cloudbuild.yaml"