دليل عملي

‎Laravel Octane على ‎VPS: ‎FrankenPHP و‎Docker و‎Traefik

التطوير11 دقيقةً للقراءةعدد الخطوات: 9

يُنشئ ‎PHP-FPM عملية لكل طلب — فعّال للتطبيقات الصغيرة، لكنه مكلف مع تزايد حركة المرور. يُغيّر ‎Laravel Octane هذا النهج: يُحمَّل التطبيق مرة واحدة في الذاكرة ويستجيب لآلاف الطلبات دون إعادة تهيئة. الكسب حقيقي: تُظهر المعايير الرسمية لـ ‎Laravel أرباحاً من ‎4× إلى ‎6× في الطلبات/الثانية مقارنةً بـ ‎PHP-FPM 8.3. ‎FrankenPHP، برنامج تشغيل ‎Octane الموصى به منذ ‎Laravel 11، يدمج خادم ‎HTTP مباشرة في الثنائي ‎PHP — لا حاجة لـ ‎nginx أمامه. على ‎VPS مع وصول ‎root و‎Docker Compose و‎Traefik، تكون عملية الترحيل نظيفة وقابلة للتكرار.

المحتويات· ‎PHP-FPM مقابل ‎Laravel Octane — ما الذي يتغير فعلاً1/10
  1. 01‎PHP-FPM مقابل ‎Laravel Octane — ما الذي يتغير فعلاً
  2. 02ست فروق هيكلية يجب معرفتها
  3. 03المتطلبات الأساسية قبل البدء
  4. 04نشر ‎Laravel Octane + ‎FrankenPHP + ‎Traefik في ‎Docker Compose
  5. 05قائمة التحقق من التوافق قبل التبديل إلى الإنتاج
  6. 068 نقاط يجب التحقق منها
  7. 07‎FrankenPHP مقابل ‎Swoole مقابل ‎RoadRunner: اختيار برنامج تشغيل ‎Octane
  8. 08مراقبة ‎Octane في الإنتاج باستخدام ‎octane:status
  9. 09استكشاف الأخطاء: أخطاء الإنتاج الشائعة
  10. 10لمزيد من المعلومات

‎PHP-FPM مقابل ‎Laravel Octane — ما الذي يتغير فعلاً

يتبع ‎PHP-FPM نموذج «لا شيء مشترك»: كل طلب يُحمّل الإطار من الصفر، وينفذ الكود، ويحرر الذاكرة. هذا متين بالتصميم — أي تسريب في طلب ما يموت معه. ‎Octane يكسر هذا العقد. يُهيّأ التطبيق مرة واحدة، ثم تتتالى الطلبات في نفس العملية. المكسب في الأداء هائل، لكن مسؤولية المطوّر تزداد.

ست فروق هيكلية يجب معرفتها

  • دورة حياة مشتركة — حاوية ‎IoC الخاصة بـ ‎Laravel والمزودين والـ ‎singletons تُنشأ مرة واحدة وتبقى بين جميع طلبات العامل. قيمة مكتوبة في ‎singleton في الطلب ‎N لا تزال موجودة في الطلب ‎N+1.
  • مكسب أداء موثق — تُظهر معايير توثيق ‎Laravel Octane الرسمية ‎4× إلى ‎6× طلبات/ثانية مقارنةً بـ ‎PHP-FPM 8.3 على نقاط نهاية نموذجية، بفضل حذف تهيئة ‎PHP في كل طلب.
  • المتغيرات الثابتة = تسريبات مضمونة — أي خاصية ‎static مكتوبة خلال طلب تلوث الطلبات التالية. واجهات ‎Laravel Facades تخفي مراجع ثابتة؛ بعضها يُنظّفه ‎Octane والبعض الآخر لا.
  • الملفات الثابتة تُخدَم بواسطة ‎FrankenPHP — يتضمن الثنائي خادم ‎HTTP كاملاً. على ‎VPS، لا حاجة لـ ‎nginx أمام ‎PHP: يتعامل ‎FrankenPHP مع ‎TLS و‎HTTP/2 و‎HTTP/3 بشكل أصلي.
  • ذاكرة ‎RSS مستقرة ≠ ذاكرة مسربة — ترتفع ذاكرة العملية عند بدء التشغيل ثم تستقر. التسريب الحقيقي يظهر كنمو مستمر عبر آلاف الطلبات، ليس المستوى الأولي.
  • العمال والتزامن — يبدأ ‎Octane ‎--workers=N عملية. كل عامل يحتفظ بحالته الخاصة، لكن نفس العامل يعالج طلباته بالتسلسل.
  • توافق ‎Laravel 10 و11 — ‎Octane 2.x يدعم ‎Laravel 10+. ‎FrankenPHP كبرنامج تشغيل متاح منذ ‎laravel/octane 2.3. ‎PHP 8.2 كحد أدنى، ‎PHP 8.3 موصى به.

المتطلبات الأساسية قبل البدء

‎VPS مع 2 ‎GB RAM على الأقل (‎4 GB موصى به لـ ‎stack كامل مع ‎Redis وعمال الطوابير)، وصول ‎root، ‎Docker 25+ و‎Docker Compose v2. يجب أن يعمل التطبيق على ‎Laravel 10 أو 11 مع تثبيت ‎laravel/octane 2.x. سيدير ‎Traefik 3.x شهادات ‎Let's Encrypt وتوجيه ‎HTTPS. لا حاجة لـ ‎nginx إضافي: ‎FrankenPHP يستبدل طبقة ‎HTTP بالكامل.

نشر ‎Laravel Octane + ‎FrankenPHP + ‎Traefik في ‎Docker Compose

  1. تثبيت ‎laravel/octane ونشر الإعداد

    في مشروع ‎Laravel:

    composer require laravel/octane
    php artisan octane:install --server=frankenphp

    هذا ينشر config/octane.php ويضيف متغيرات البيئة إلى .env.example. تحقق من تعيين OCTANE_SERVER=frankenphp.

  2. كتابة ‎Dockerfile لـ ‎FrankenPHP

    FROM dunglas/frankenphp:1-php8.3-alpine
    
    RUN install-php-extensions \
        pdo_mysql \
        redis \
        opcache \
        pcntl \
        zip \
        intl
    
    WORKDIR /app
    
    COPY --chown=www-data:www-data . .
    
    RUN composer install --no-dev --optimize-autoloader --no-interaction \
     && php artisan config:cache \
     && php artisan route:cache \
     && php artisan view:cache
    
    EXPOSE 8000
    
    CMD ["php", "artisan", "octane:frankenphp", "--host=0.0.0.0", "--port=8000", "--workers=4", "--max-requests=500"]

    خيار --max-requests=500 يُعيد تشغيل العامل بعد 500 طلب: شبكة أمان ضد تسريبات الذاكرة المتبقية.

  3. كتابة ‎docker-compose.yml الكامل

    services:
      app:
        build: .
        restart: unless-stopped
        environment:
          APP_ENV: production
          APP_KEY: ${APP_KEY}
          DB_HOST: db
          REDIS_HOST: redis
          CACHE_DRIVER: redis
          SESSION_DRIVER: redis
          QUEUE_CONNECTION: redis
          OCTANE_SERVER: frankenphp
        networks:
          - internal
          - traefik
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.app.entrypoints=websecure"
          - "traefik.http.routers.app.tls.certresolver=letsencrypt"
          - "traefik.http.services.app.loadbalancer.server.port=8000"
        depends_on:
          db:
            condition: service_healthy
          redis:
            condition: service_healthy
    
      worker:
        build: .
        restart: unless-stopped
        command: ["php", "artisan", "queue:work", "redis", "--sleep=3", "--tries=3", "--max-time=3600"]
        networks:
          - internal
        depends_on:
          db:
            condition: service_healthy
          redis:
            condition: service_healthy
    
      scheduler:
        build: .
        restart: unless-stopped
        command: ["sh", "-c", "while true; do php artisan schedule:run >> /dev/null 2>&1; sleep 60; done"]
        networks:
          - internal
    
      db:
        image: mysql:8.0
        restart: unless-stopped
        volumes:
          - db_data:/var/lib/mysql
        networks:
          - internal
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
          interval: 10s
          timeout: 5s
          retries: 5
    
      redis:
        image: redis:7-alpine
        restart: unless-stopped
        volumes:
          - redis_data:/data
        networks:
          - internal
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
          interval: 10s
          timeout: 3s
          retries: 5
    
    volumes:
      db_data:
      redis_data:
    
    networks:
      internal:
      traefik:
        external: true
  4. نشر ‎Traefik مع شهادات تلقائية

    docker network create traefik
    mkdir -p /opt/traefik/letsencrypt
    touch /opt/traefik/letsencrypt/acme.json
    chmod 600 /opt/traefik/letsencrypt/acme.json
    docker compose -f /opt/traefik/docker-compose.yml up -d
  5. ‫تهيئة ملف ‎.env‬ للإنتاج

    المتغيرات الأساسية التي يجب تعريفها على ‎VPS‬:

    APP_ENV=production
    APP_DEBUG=false
    APP_KEY=base64:...  # يُنشأ بـ php artisan key:generate
    DOMAIN=your-domain.com
    DB_DATABASE=laravel
    DB_USERNAME=laravel
    DB_PASSWORD=strong_password
    DB_ROOT_PASSWORD=root_strong_password
    OCTANE_SERVER=frankenphp
    CACHE_DRIVER=redis
    SESSION_DRIVER=redis
    QUEUE_CONNECTION=redis

    لا تُودّع ‎.env‬ في ‎git‬ أبدًا. على ‎VPS‬، أدِره عبر ‎scp‬ أو مدير الأسرار.

  6. تشغيل عمليات الترحيل بدون توقف

    docker compose run --rm app php artisan migrate --force

    للنشر بدون توقف، استخدم علامة --step على الترحيلات التي تضيف أعمدة ‎NOT NULL.

  7. تشغيل الـ ‎stack والتحقق من ‎healthcheck

    docker compose up -d --build
    docker compose ps

    انتظر حتى يصل ‎db و‎redis إلى حالة ‎healthy قبل أن يبدأ ‎app.

  8. التحقق من الحالة باستخدام ‎octane:status

    docker compose exec app php artisan octane:status

    تعرض هذه الأمر الخادم النشط (‎frankenphp)، عدد العمال وحالتهم. استجابة ‎running تؤكد أن العمال يستجيبون.

  9. إعادة تحميل العمال عند النشر

    docker compose build app worker scheduler
    docker compose up -d --no-deps app worker scheduler

    لإعادة التحميل بدون قطع الاتصالات النشطة:

    docker compose exec app php artisan octane:reload

قائمة التحقق من التوافق قبل التبديل إلى الإنتاج

الانتقال إلى ‎Octane لا يتطلب إعادة كتابة التطبيق، لكن بعض الأنماط الشائعة تنكسر بصمت. راجع هذه القائمة على كودك قبل أول نشر.

8 نقاط يجب التحقق منها

  • ‎Singletons ذات حالة قابلة للتغيير — أي خدمة مسجلة بـ ‎$this->app->singleton() تخزن بيانات خاصة بالطلب يجب إعادة تهيئتها في ‎OctaneServiceProvider. مراجعة: ‎grep -r 'singleton' app/Providers.
  • الجلسات — مع ‎SESSION_DRIVER=redis تصمد الجلسات بشكل صحيح. قد يُسبب برنامج التشغيل ‎file حالات تنافس مع عمال متعددين. الترحيل إلى ‎redis أو ‎database موصى به.
  • اتصالات قاعدة البيانات — يحتفظ ‎Octane باتصالات ‎DB دائمة لكل عامل. تحقق من أن ‎MySQL يقبل ‎max_connections ≥ workers × replicas.
  • المتغيرات الثابتة في النماذج أو الخدمات — ‎static $cache = [] في نموذج ‎Eloquent يستمر بين الطلبات. استبدله بحقن التبعية بنطاق الطلب.
  • مستمعو الأحداث غير الأكفاء — مستمع مسجل في ‎boot() يُسجَّل مرة واحدة فقط، لكنه يُنفَّذ في كل طلب يُطلق الحدث. مشكلة فقط إذا كان يجمع حالة عامة.
  • المهام والطوابير — لا تعمل ‎Jobs في عملية ‎Octane الرئيسية بل في حاوية ‎worker منفصلة. لا تعديلات مطلوبة على كود ‎Jobs.
  • الملفات المرفوعة والتخزين — تأكد من تركيب مجلد ‎/app/storage كـ ‎volume لكي تستمر الملفات بين إعادة بناء الصورة.
  • الحزم التابعة لجهات خارجية — تحقق من توافق ‎Octane لكل حزمة تستخدمها. عطّل ‎Debugbar وTelescope في الإنتاج.

‎FrankenPHP مقابل ‎Swoole مقابل ‎RoadRunner: اختيار برنامج تشغيل ‎Octane

مرّر الجدول أفقيًا

المعيارFrankenPHPSwooleRoadRunner
التثبيتصورة ‎Docker رسمية ‎`dunglas/frankenphp` — لا حاجة لتجميع امتداد ‎PECLامتداد ‎PECL ‎`swoole` — يتطلب ‎`pecl install swoole` أو صورة مخصصةثنائي ‎Go منفصل (`roadrunner`) — يُنزَّل عبر ‎Composer
HTTP/2 و‎HTTP/3أصلي — ‎FrankenPHP مبني على ‎Caddy الذي يدعم ‎HTTP/3 (QUIC) تلقائياًيدعم ‎HTTP/2، ‎HTTP/3 ليس أصلياً‎HTTP/2 عبر مكوّن إضافي، ‎HTTP/3 غير مدعوم أصلياً
توافق امتدادات ‎PHPواسع جداً — مبني على ‎PHP-FPM الرسمي، معظم الامتدادات تُثبَّت بشكل طبيعيعدم توافق معروف مع بعض الامتدادات الحاجبةواسع، لكن بعض امتدادات ‎PECL قد تحتاج تكيفات
توصية ‎Laravel الرسميةبرنامج التشغيل الموصى به منذ ‎Laravel 11 (2024)، مذكور أولاً في وثائق ‎Octaneبرنامج التشغيل الأولي التاريخي، لا يزال مدعوماًمدعوم، بديل لـ ‎Swoole، شائع في نظام ‎Symfony
تعقيد التشغيلمنخفض — حاوية واحدة، ‎Dockerfile بسيط، لا خادم منفصلمتوسط — يجب تجميع الامتداد مع نسخة ‎PHP الصحيحةمتوسط — يجب مزامنة ثنائي ‎RoadRunner مع نسخة حزمة ‎Composer

مراقبة ‎Octane في الإنتاج باستخدام ‎octane:status

تستعلم الأمر ‎php artisan octane:status عن خادم ‎FrankenPHP في الوقت الفعلي وتعرض عدد العمال النشطين والحالة الإجمالية. دمجها في المراقبة:

docker compose exec -T app php artisan octane:status | grep -q 'running' && echo OK || echo FAIL

لإعادة تحميل العمال بدون قطع الاتصالات:

docker compose exec app php artisan octane:reload

راقب ذاكرة ‎RSS للعملية الرئيسية: النمو المستمر يشير إلى تسريب. الأمر ‎docker stats app يعطي الذاكرة في الوقت الفعلي.

استكشاف الأخطاء: أخطاء الإنتاج الشائعة

تسريب ذاكرة تدريجي: ذاكرة الحاوية ‎app تنمو باستمرار. السبب المحتمل: ‎singleton يجمع بيانات لكل طلب. قلل ‎--max-requests إلى 100 ريثما تحدد المصدر.

‎502 Bad Gateway من ‎Traefik: تحقق من أن الحاوية على شبكة ‎traefik، وأن التسمية ‎traefik.http.services.app.loadbalancer.server.port=8000 تطابق المنفذ المكشوف، وأن الحاوية في حالة ‎healthy.

عامل يُعيد التشغيل في حلقة: ابحث عن ‎FATAL في ‎docker compose logs app. السبب الأكثر شيوعاً: ترحيل لم يُنفَّذ يرفع ‎QueryException.

جلسات مفقودة بين الطلبات: انتقل إلى ‎SESSION_DRIVER=redis.

منطقة زمنية خاطئة: أضف ‎APP_TIMEZONE في ‎.env و‎RUN apk add --no-cache tzdata في ‎Dockerfile.

لمزيد من المعلومات

لديك الآن ‎stack عامل لـ ‎Laravel Octane على ‎VPS. المقالات التالية تغطي الخطوات التالية الطبيعية: [نشر ‎Laravel على ‎VPS](/blog/deployer-laravel-vps)، [النشر مع ‎Traefik](/blog/deployer-avec-traefik)، [قائمة فحص ‎Docker Compose للإنتاج](/blog/docker-compose-production-checklist)، [استضافة ‎Redis على ‎VPS](/blog/heberger-redis-vps)، [نهاية عمر ‎PHP 8.2](/blog/php-82-fin-de-vie-checklist-migration).

انشر بنيتك التحتية اليوم

VPS Cloud. بيئات مُهيّأة مسبقًا متاحة.

مقالات ذات صلة

نشر Laravel على خادم VPS: دليل الإنتاج
التطوير4 دقائق للقراءة

نشر Laravel على خادم VPS: دليل الإنتاج

انقل Laravel إلى بيئة الإنتاج على خادم VPS: PHP وworkers والذاكرة المؤقتة وقاعدة البيانات وreverse proxy وHTTPS مُهيّأة بشكل نظيف.

قراءة المقال ←
انشر تطبيقاتك باستخدام Traefik على خادم VPS
النشر3 دقائق للقراءة

انشر تطبيقاتك باستخدام Traefik على خادم VPS

انشر Traefik كوكيل عكسي على خادم VPS الخاص بك: توجيه تلقائي لحاويات Docker، وشهادات SSL من Let's Encrypt، وموازنة أحمال.

قراءة المقال ←
Docker Compose في الإنتاج: قائمة التحقق من 10 نقاط
النشر12 دقيقةً للقراءة

Docker Compose في الإنتاج: قائمة التحقق من 10 نقاط

‏قائمة تحقق Docker Compose للإنتاج: 10 إعدادات أساسية، فحوصات صحية، أسرار بدون توقف، استراتيجية التراجع، استكشاف الأخطاء الشائعة.

قراءة المقال ←
استضافة ‎Redis‎ على خادم ‎VPS‎: الدليل الشامل
قواعد البيانات10 دقائق للقراءة

استضافة ‎Redis‎ على خادم ‎VPS‎: الدليل الشامل

انشر ‎Redis‎ على خادم ‎VPS‎ السحابي: متطلبات ‎RAM‎ و‎CPU‎، الأمان (‎ACL‎ و‎TLS‎)، استمرارية ‎RDB/AOF‎، استكشاف الأخطاء والتوافر العالي.

قراءة المقال ←
نهاية دعم PHP 8.2 : قائمة التحقق للترحيل
التطوير11 دقيقةً للقراءة

نهاية دعم PHP 8.2 : قائمة التحقق للترحيل

يبلغ PHP 8.2 نهاية دورة حياته في 31 ديسمبر 2026. جرد بيئاتك، قارن الإصدارات، واتبع قائمة تحقق مفصّلة للترحيل إلى PHP 8.3 أو 8.4.

قراءة المقال ←

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة