Alaa Amer Articles

We offer a comprehensive collection of essential educational articles in web development to turn your ideas into digital reality

Deployment & DevOps: Laravel Production Deployment Mastery

Laravel 2026-01-01 Alaa Amer

Deployment & DevOps: Laravel Production Deployment Mastery

Expert Guide by Alaa Amer – Professional Web Developer & Applications Designer

Master Laravel deployment and DevOps practices for production environments. Learn CI/CD, containerization, monitoring, scaling strategies, and enterprise-level infrastructure management.

Docker Compose for Production:

# docker-compose.prod.yml
version: "3.8"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    image: laravel-app:latest
    restart: unless-stopped
    environment:
      - APP_ENV=production
      - APP_DEBUG=false
    volumes:
      - ./storage:/var/www/html/storage
      - ./bootstrap/cache:/var/www/html/bootstrap/cache
    networks:
      - laravel-network
    depends_on:
      - database
      - redis
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "1"
          memory: 512M
        reservations:
          cpus: "0.5"
          memory: 256M

  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./docker/nginx/ssl:/etc/ssl/certs
      - ./storage/app/public:/var/www/html/storage/app/public
    networks:
      - laravel-network
    depends_on:
      - app

  database:
    image: mysql:8.0
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_USER: ${DB_USERNAME}
    volumes:
      - db-data:/var/lib/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/custom.cnf
    networks:
      - laravel-network
    command: --innodb-buffer-pool-size=1G --innodb-log-file-size=256M

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - redis-data:/data
      - ./docker/redis/redis.conf:/etc/redis/redis.conf
    networks:
      - laravel-network
    command: redis-server /etc/redis/redis.conf

  queue-worker:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    restart: unless-stopped
    command: php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
    volumes:
      - ./storage:/var/www/html/storage
    networks:
      - laravel-network
    depends_on:
      - database
      - redis
    deploy:
      replicas: 3

  scheduler:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    restart: unless-stopped
    command: php artisan schedule:work
    volumes:
      - ./storage:/var/www/html/storage
    networks:
      - laravel-network
    depends_on:
      - database
      - redis

volumes:
  db-data:
  redis-data:

networks:
  laravel-network:
    driver: bridge

4️⃣ Monitoring & Observability

Application Monitoring Setup:

<?php
// app/Http/Middleware/ApplicationMonitoring.php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\{Log, Cache, DB};
use Prometheus\CollectorRegistry;
use Prometheus\Storage\Redis;

class ApplicationMonitoring
{
    protected $registry;

    public function __construct()
    {
        $this->registry = new CollectorRegistry(new Redis());
    }

    public function handle(Request $request, Closure $next)
    {
        $startTime = microtime(true);

        $response = $next($request);

        $duration = microtime(true) - $startTime;

        // Record metrics
        $this->recordMetrics($request, $response, $duration);

        return $response;
    }

    protected function recordMetrics(Request $request, $response, float $duration): void
    {
        // HTTP request duration
        $histogram = $this->registry->getOrRegisterHistogram(
            'laravel_app',
            'http_request_duration_seconds',
            'HTTP request duration in seconds',
            ['method', 'route', 'status_code'],
            [0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]
        );

        $histogram->observe(
            $duration,
            [
                $request->method(),
                $request->route()?->getName() ?? 'unknown',
                (string) $response->getStatusCode()
            ]
        );

        // HTTP request count
        $counter = $this->registry->getOrRegisterCounter(
            'laravel_app',
            'http_requests_total',
            'Total number of HTTP requests',
            ['method', 'status_code']
        );

        $counter->inc([
            $request->method(),
            (string) $response->getStatusCode()
        ]);

        // Database query count
        if (DB::getQueryLog()) {
            $queryGauge = $this->registry->getOrRegisterGauge(
                'laravel_app',
                'database_queries_per_request',
                'Number of database queries per request'
            );

            $queryGauge->set(count(DB::getQueryLog()));
        }

        // Memory usage
        $memoryGauge = $this->registry->getOrRegisterGauge(
            'laravel_app',
            'memory_usage_bytes',
            'Memory usage in bytes'
        );

        $memoryGauge->set(memory_get_peak_usage(true));
    }
}

// app/Console/Commands/MonitorSystem.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\{DB, Cache, Queue};

class MonitorSystem extends Command
{
    protected $signature = 'monitor:system';
    protected $description = 'Monitor system health and send alerts';

    public function handle(): void
    {
        $this->info('Running system monitoring...');

        $checks = [
            'database' => $this->checkDatabase(),
            'cache' => $this->checkCache(),
            'queue' => $this->checkQueue(),
            'storage' => $this->checkStorage(),
            'memory' => $this->checkMemory(),
            'logs' => $this->checkLogs()
        ];

        $failures = array_filter($checks, fn($status) => !$status);

        if (!empty($failures)) {
            $this->sendAlert($failures);
            $this->error('System health check failed: ' . implode(', ', array_keys($failures)));
        } else {
            $this->info('All system checks passed');
        }

        $this->recordHealthMetrics($checks);
    }

    protected function checkDatabase(): bool
    {
        try {
            DB::select('SELECT 1');

            // Check slow queries
            $slowQueries = DB::select("
                SELECT COUNT(*) as slow_count
                FROM information_schema.processlist
                WHERE command != 'Sleep' AND time > 30
            ");

            return $slowQueries[0]->slow_count < 5;
        } catch (\Exception $e) {
            Log::error('Database health check failed', ['error' => $e->getMessage()]);
            return false;
        }
    }

    protected function checkCache(): bool
    {
        try {
            $testKey = 'health_check_' . time();
            Cache::put($testKey, 'test', 60);
            $result = Cache::get($testKey);
            Cache::forget($testKey);

            return $result === 'test';
        } catch (\Exception $e) {
            Log::error('Cache health check failed', ['error' => $e->getMessage()]);
            return false;
        }
    }

    protected function checkQueue(): bool
    {
        try {
            // Check queue sizes
            $queueSizes = [
                'default' => Queue::size('default'),
                'high' => Queue::size('high'),
                'emails' => Queue::size('emails')
            ];

            // Alert if any queue has too many jobs
            return !collect($queueSizes)->contains(fn($size) => $size > 1000);
        } catch (\Exception $e) {
            Log::error('Queue health check failed', ['error' => $e->getMessage()]);
            return false;
        }
    }

    protected function checkStorage(): bool
    {
        $storagePath = storage_path();
        $freeSpace = disk_free_space($storagePath);
        $totalSpace = disk_total_space($storagePath);

        $usagePercent = (($totalSpace - $freeSpace) / $totalSpace) * 100;

        return $usagePercent < 90; // Alert if usage > 90%
    }

    protected function checkMemory(): bool
    {
        $memoryUsage = memory_get_usage(true);
        $memoryLimit = $this->parseMemoryLimit(ini_get('memory_limit'));

        $usagePercent = ($memoryUsage / $memoryLimit) * 100;

        return $usagePercent < 90;
    }

    protected function checkLogs(): bool
    {
        $logPath = storage_path('logs/laravel.log');

        if (!file_exists($logPath)) {
            return true;
        }

        // Check for recent errors
        $recentErrors = shell_exec("grep -c 'ERROR' $logPath | tail -1000");

        return intval($recentErrors) < 50; // Alert if > 50 errors in last 1000 lines
    }

    protected function parseMemoryLimit(string $limit): int
    {
        $limit = trim($limit);
        $last = strtolower($limit[strlen($limit) - 1]);
        $limit = (int) $limit;

        switch ($last) {
            case 'g': $limit *= 1024 * 1024 * 1024; break;
            case 'm': $limit *= 1024 * 1024; break;
            case 'k': $limit *= 1024; break;
        }

        return $limit;
    }

    protected function sendAlert(array $failures): void
    {
        // Send to monitoring service (Slack, PagerDuty, etc.)
        Log::critical('System health check failures detected', $failures);

        // You could integrate with external services here
        // Notification::route('slack', '#alerts')->notify(new SystemHealthAlert($failures));
    }

    protected function recordHealthMetrics(array $checks): void
    {
        foreach ($checks as $service => $status) {
            Cache::put("health_check:{$service}", $status ? 1 : 0, 300);
        }
    }
}

Grafana Dashboard Configuration:

{
  "dashboard": {
    "title": "Laravel Application Metrics",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(laravel_app_http_requests_total[5m])",
            "legendFormat": "{{method}} {{status_code}}"
          }
        ]
      },
      {
        "title": "Response Time",
        "type": "graph",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, rate(laravel_app_http_request_duration_seconds_bucket[5m]))",
            "legendFormat": "95th percentile"
          },
          {
            "expr": "histogram_quantile(0.50, rate(laravel_app_http_request_duration_seconds_bucket[5m]))",
            "legendFormat": "50th percentile"
          }
        ]
      },
      {
        "title": "Database Queries",
        "type": "graph",
        "targets": [
          {
            "expr": "avg(laravel_app_database_queries_per_request)",
            "legendFormat": "Avg queries per request"
          }
        ]
      },
      {
        "title": "Memory Usage",
        "type": "graph",
        "targets": [
          {
            "expr": "laravel_app_memory_usage_bytes",
            "legendFormat": "Memory usage"
          }
        ]
      }
    ]
  }
}

Production Deployment Checklist

Security Configuration

  • SSL certificates installed
  • Security headers configured
  • Firewall rules applied
  • Database credentials secured

Performance Optimization

  • Opcache enabled
  • Asset compression configured
  • CDN integration completed
  • Database indexes optimized

Monitoring Setup

  • Application monitoring configured
  • Error tracking enabled
  • Log aggregation implemented
  • Alert notifications configured

Backup Strategy

  • Database backup automated
  • File backup configured
  • Backup restoration tested
  • Offsite backup storage

High Availability

  • Load balancer configured
  • Multiple application instances
  • Database replication setup
  • Queue workers running

📩 Need help with Laravel deployment?

Laravel Deployment DevOps Docker CI/CD Server Management Production Monitoring Scaling
Article Category
Laravel

Deployment & DevOps: Laravel Production Deployment Mastery

Master Laravel deployment strategies, CI/CD pipelines, Docker containerization, server management, monitoring, and enterprise-level DevOps practices.

Deployment & DevOps: Laravel Production Deployment Mastery
01

Consultation & Communication

Direct communication via WhatsApp or phone to understand your project needs precisely.

02

Planning & Scheduling

Creating clear work plan with specific timeline for each project phase.

03

Development & Coding

Building projects with latest technologies ensuring high performance and security.

04

Testing & Delivery

Comprehensive testing and thorough review before final project delivery.

Alaa Amer
Alaa Amer

Professional web developer with over 10 years of experience in building innovative digital solutions.

Need This Service?

Contact me now for a free consultation and quote

WhatsApp Your satisfaction is our ultimate goal

What We Offer

  • Website Maintenance & Updates

    Keep your website secure updated optimized

  • API Integration

    Connect your systems with powerful APIs

  • Database Design & Optimization

    Faster queries cleaner structure fewer issues

  • Website Security Hardening

    Protect your site from cyber threats

  • Automation & Scripts

    Automate repetitive tasks and save time

Have Questions?

Call Us Now

00201014714795