← كل المقالات

نشر Laravel بدون توقف مع خطة رجوع آمنة

ابنِ مسار نشر Laravel بدون توقف باستخدام مجلدات إصدارات وتبديل ذري وMigrations متوافقة وإعادة تشغيل الطوابير وفحوص صحة وخطة رجوع واضحة.

يبني بكري عبدالسلام مواقع الويب والتطبيقات والتكاملات ومنتجات ووردبريس، ويوثق مركز بكري التقني القرارات التقنية وراء هذا العمل.

الخلاصة

جهز كل إصدار في مجلد مستقل، واختبره قبل تحويل الرابط الرمزي، واجعل تغييرات قاعدة البيانات متوافقة مع الإصدارين، ثم أعد تشغيل العمال وتحقق من المسارات المهمة قبل حذف الإصدار السابق.

النشر الجيد لا يعتمد على كتابة أوامر صحيحة بسرعة وقت الضغط. ينفذ الخطوات نفسها في الترتيب نفسه، ويترك سجلاً يبين أي إصدار يعمل، ويجعل الرجوع إلى نسخة سابقة إجراءً معروفاً.

على خادم Linux واحد أو مجموعة صغيرة من الخوادم، توفر مجلدات الإصدارات مع رابط رمزي أساساً واضحاً لنشر Laravel بدون انقطاع ملحوظ. لكنها لا تكفي وحدها؛ قاعدة البيانات والطوابير والجلسات والأصول تحتاج إلى التوافق أيضاً.

افهم ما يعنيه «بدون توقف»

لا يعني المصطلح أن كل تغيير يمكن نشره بلا مخاطرة. يعني أن التحويل بين نسختين لا يترك الموقع في حالة نصف محدثة، وأن الطلبات القديمة تستطيع الاكتمال بينما تبدأ الطلبات الجديدة على الإصدار الجديد.

إذا كان التطبيق يكتب ملفات محلية أو يحتفظ بجلسات على خادم واحد أو ينفذ Migration تحذف عموداً مستخدماً، فلن يصلح الرابط الرمزي هذه المشكلات. اعتبر النشر عملية توافق بين عدة مكونات، لا تبديل مجلد فقط.

استخدم مجلداً مستقلاً لكل إصدار

بنية عملية:

/var/www/app/
├── current -> releases/20260801-184500
├── releases/
│   ├── 20260728-102200/
│   └── 20260801-184500/
└── shared/
    ├── .env
    └── storage/

يشير Nginx إلى /var/www/app/current/public. جهز الإصدار الجديد كاملاً داخل releases، واربط .env وstorage المشتركتين، ثم غيّر current في خطوة ذرية.

لا تنفذ git pull داخل المجلد الحي. قد تصل الطلبات بينما تغيرت بعض الملفات ولم تصل بقية الاعتمادات أو الأصول.

ابنِ الإصدار قبل تحويل الزيارات

يجب أن يمثل المجلد Commit محددة وقابلة للتتبع. نفذ التثبيت والبناء بإعدادات الإنتاج:

composer install \
  --no-dev \
  --prefer-dist \
  --no-interaction \
  --optimize-autoloader

php artisan config:cache
php artisan route:cache
php artisan view:cache

ابنِ أصول الواجهة في بيئة مضبوطة، أو انشر ناتج بناء مرتبطاً بالـCommit نفسها. ولا تجعل خادم الإنتاج يسحب أحدث حزم غير مثبتة في ملف Lock.

قبل التحويل تحقق من وجود الملفات المشتركة وصلاحيات storage وbootstrap/cache، وأن ملف الأصول المبنية يشير إلى ملفات موجودة.

افحص الإصدار الجديد قبل جعله حياً

شغّل فحصاً لا يحتاج إلى المرور عبر الرابط current. يمكن أن يكون أمراً داخل التطبيق أو طلباً إلى منفذ محلي أو اسم مضيف مخصصاً للإصدار.

يجب أن يثبت الفحص على الأقل:

  • إقلاع Laravel بلا خطأ.
  • تحميل الإعدادات والاعتمادات.
  • الوصول إلى قاعدة البيانات وCache إذا كانا ضروريين للخدمة.
  • وجود الأصول المطلوبة.
  • نجاح مسار صحي خفيف.

لا تجعل Health Check تعيد 200 دائماً من Nginx؛ يجب أن تصل إلى التطبيق، لكن من دون تنفيذ عملية ثقيلة قد تجعل نظام المراقبة نفسه مصدر ضغط.

اجعل تغييرات قاعدة البيانات متوافقة مع إصدارين

قد تعمل النسخة القديمة والجديدة معاً لثوانٍ، وقد تبقى مهمة طابور قديمة في الذاكرة بعد تبديل الرابط. لذلك استخدم نمط التوسيع ثم التقليص:

  1. أضف العمود أو الجدول الجديد من دون حذف القديم.
  2. انشر كوداً يستطيع القراءة والكتابة في الشكلين عند الحاجة.
  3. انقل البيانات القديمة في عملية منفصلة قابلة للمراقبة.
  4. حوّل القراءة إلى البنية الجديدة.
  5. احذف البنية القديمة في إصدار لاحق بعد التأكد من عدم استخدامها.

تجنب إعادة تسمية عمود أو حذفه في الإصدار نفسه الذي يتوقف عن استخدامه. وبناء Index على جدول ضخم أو تعديل كل الصفوف يحتاج خطة تشغيل مستقلة وفق محرك قاعدة البيانات.

لا تعتمد على migrate:rollback كخطة عامة؛ قد تحذف بيانات كُتبت بعد النشر. غالباً يكون إصلاح البيانات إلى الأمام أكثر أماناً من عكسها.

بدّل الرابط الرمزي في عملية واحدة

بعد اكتمال البناء والفحص والتغييرات المتوافقة، أنشئ رابطاً مؤقتاً ثم انقله فوق current:

ln -s /var/www/app/releases/20260801-184500 /var/www/app/current-next
mv -Tf /var/www/app/current-next /var/www/app/current

تحقق من سلوك mv في نظام التشغيل المستخدم، ولا تبنِ أمر النشر من مسار غير موثوق. يجب أن يشير Nginx ومدير العمليات إلى current لا إلى رقم إصدار ثابت.

احتفظ بالإصدار السابق ولا تنظفه قبل نجاح التحقق بعد التحويل.

أعد تشغيل عمال الطابور في الوقت الصحيح

عامل Laravel عملية طويلة العمر تحمل الكود في الذاكرة. بعد تحويل current اطلب منها إنهاء المهمة الحالية والخروج:

php artisan queue:restart

يجب أن يعيد Supervisor تشغيل العامل من المسار الجديد. افحص أن Cache التي تحمل إشارة إعادة التشغيل مشتركة مع العمال، وأن stopwaitsecs أطول من أطول مهمة شرعية.

راقب طابوراً حقيقياً أو أرسل مهمة فحص آمنة. نجاح الصفحة الرئيسية لا يثبت أن البريد أو Webhooks أو التقارير تعمل. راجع دليل Laravel Queue وSupervisor عند توقف المعالجة.

نسق المجدول والجلسات والتخزين

يجب أن تستدعي Cron المسار current/artisan حتى تنتقل تلقائياً إلى الإصدار الجديد. وبعد النشر افحص schedule:list ووقت آخر مهمة مهمة؛ حالة خدمة Cron وحدها غير كافية.

إذا كانت هناك عدة نسخ للتطبيق، استخدم مخزناً مشتركاً للجلسات وCache والأقفال، ولا تعتمد على ملفات محلية. أما ملفات المستخدمين فضعها في مساحة مشتركة أو Object Storage بدلاً من مجلد الإصدار الذي سيُحذف لاحقاً.

تحقق بعد التحويل ثم قرر الاستمرار

بعد تبديل الرابط نفذ فحوصاً قصيرة ذات معنى:

  1. الصفحة العامة أو API الصحية.
  2. تسجيل الدخول أو التحقق من جلسة موجودة.
  3. عملية قراءة وكتابة غير مؤذية في قاعدة البيانات.
  4. تحميل ملف أصل من الإصدار الجديد.
  5. تنفيذ مهمة طابور.
  6. عدم ارتفاع أخطاء 5xx أو زمن الاستجابة.

سجل رقم الإصدار ووقت التحويل ونتيجة الفحوص. إذا فشل شرط أساسي، أوقف بقية الخطوات وانتقل إلى خطة الرجوع المعروفة.

اجعل الرجوع عملية معتادة

للرجوع في الكود، أعد current إلى الإصدار السابق ثم أعد تشغيل العمال وأعد الفحوص. احتفظ بعدة إصدارات قريبة وحدد أيها متوافق مع قاعدة البيانات الحالية.

لا تَعُد إلى كود لا يفهم عموداً جديداً إجبارياً أو تغييراً غير قابل للعكس. لهذا تفصل خطة النشر بين رجوع الكود وإصلاح البيانات إلى الأمام.

جرّب أمر الرجوع في Staging دورياً. الخطة التي لم تُنفذ من قبل ليست ضماناً وقت الحادث.

نظف بعد التأكد لا قبله

بعد فترة مراقبة مناسبة:

  • احذف الإصدارات القديمة مع إبقاء عدد معروف.
  • نظف ملفات مؤقتة لا تحتاجها.
  • راجع مساحة القرص والسجلات.
  • وثق أي خطوة يدوية ظهرت أثناء النشر وحولها إلى خطوة آلية أو تحقق واضح.

لا تحذف مجلد shared أو الإصدار الذي تحتاجه للرجوع. اجعل سكربت التنظيف يقبل مساراً ثابتاً ويتحقق منه قبل الحذف.

أخطاء شائعة

  • تشغيل git pull وComposer داخل المجلد الحي.
  • حذف عمود قاعدة بيانات قبل توقف كل كود قديم عن استخدامه.
  • نسيان إعادة تشغيل Queue Workers.
  • فحص الصفحة الرئيسية فقط.
  • تنظيف الإصدار السابق مباشرة بعد التحويل.
  • استخدام down() تلقائياً لقاعدة البيانات أثناء الرجوع.
  • تخزين Uploads داخل مجلد الإصدار.

أسئلة شائعة

هل أحتاج إلى أداة نشر جاهزة؟

ليست شرطاً، لكنها تقلل الأخطاء عندما تطبق المراحل نفسها بوضوح. افهم البنية أولاً، ثم اختر أداة تنفذ الإصدارات والتبديل والأقفال والسجلات بطريقة يمكن مراجعتها.

هل يمكن نشر كل تغيير في قاعدة البيانات بدون توقف؟

لا. بعض تغييرات الجداول تقفل البيانات أو تكسر النسخة السابقة. راجع أثر العملية في محرك قاعدة البيانات وحجم الجدول، واستخدم مراحل متعددة للتغييرات غير المتوافقة.

متى أعتبر النشر ناجحاً؟

بعد نجاح الفحوص الوظيفية والتشغيلية، وتشغيل العمال والمهام المجدولة، واستقرار معدل الأخطاء والوقت، مع بقاء مسار رجوع صالح خلال فترة المراقبة.

مراجع رسمية

لديك سؤال عن هذا الدليل أو فكرة لتعاون تقني؟ تواصل مع بكري عبر المركز التقني.

نهاية الملاحظة.