اذهب إلى المحتوى

سامر سليمان

الأعضاء
  • المساهمات

    13
  • تاريخ الانضمام

  • تاريخ آخر زيارة

آخر الزوار

لوحة آخر الزوار معطلة ولن تظهر للأعضاء

إنجازات سامر سليمان

عضو مساهم

عضو مساهم (2/3)

2

السمعة بالموقع

  1. يثبت مستخدمي لينكس الكثير من الحزم البرمجية باستخدام الأداة apt لما تتيحه من سهولة في العمل، فيكفي أن يكتب المستخدم اسم الحزمة لتبدأ الأداة البحث عنها ضمن مخازن البرمجيات الخاصة بنظام التشغيل أوبونتو. تكمن المشكلة الأساسية عندما لا تكون الحزمة المطلوبة موجودة ضمن مخزن البرمجيات الخاص بنظام التشغيل أوبونتو وهنا يمكن للمستخدم أن يستخدم برمجيات خارجية -مطورة من طرف ثالث Third-party كما تسمى- إن رغب بذلك كما هو الحال عند تثبيت التطبيقات باستخدام PPA ويمكن أن يتم اللجوء إلى مخزن برمجيات خارجي وتوسعة قائمة مصادر التثبيت Source List المستخدمة عند البحث عن حزمة برمجية ما. يبحث المستخدم عادة عن التعليمات اللازمة لتثبيت الحزمة فيجد مجموعة من الأوامر التي يجب عليه تنفيذها كأن يثبّت أداة ما ومن إضافة شيء ما يتعلق بمفاتيح gpg إلى قائمة مصادر التثبيت وبعدها يمكن تثبيت الحزمة البرمجية. يستعرض المثال التالي التعليمات اللازمة لتثبيت مدير الحزم الخاص بلغة جافا سكريبت JavaScript على نظام أوبونتو: sudo apt install apt-transport-https curl curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list' sudo apt update && sudo apt install yarn نجد العديد من هذه الأوامر عند تثبيت الأدوات البرمجية مباشرة من المطور وتعد المشكلة الأساسية فيها أن المستخدم ينفذ مجموعة من التعليمات الحساسة والتي تتطلب صلاحيات متقدمة بعض الشيء دون أن يدرك فعليًا دور كل أمر من الأوامر. يجب أن يدرك المستخدم الخطوات التي ينفذها مما يضمن نجاح عملية التثبيت من جهة ويسهل عملية حل المشاكل التي تصادفه. فهم إجرائية تثبيت الحزم من مخازن البرمجيات الخارجية يبين الشكل التالي توضيحًا للمخازن البرمجية ومحتوياتها ضمن نظام التشغيل لينكس. عندما نضيف مخزن برمجيات جديد إلى النظام فهذا يعني أن المستخدم يصبح قادرًا على تحميل وتثبيت الحزم البرمجية المتاحة ضمن هذا المخزن الجديد كما أنه يستطيع تحديث وترقية هذه الحزم عندما يتيحها المخزن مباشرة وذلك من ضمن عملية تحديث وترقية حزم النظام بتنفيذ الأمر apt update والأمر apt upgrade. تقسم هذه الإجرائية إلى أربعة أجزاء رئيسية وهي: الحصول على دعم بروتوكول https للأداة apt إضافة مفتاح GPG الخاص بمخزن البرمجيات البعيد إضافة عنوان مخزن البرمجيات البعيد إلى قائمة مصادر التثبيت الموثوقة تثبيت التطبيقات من المخزن البرمجي الذي تمت إضافته الجزء الأول: الحصول على دعم بروتوكول https للأداة apt بالعودة إلى التعليمات السابقة نجد أنها تبدأ بالأمر التالي: sudo apt install apt-transport-https curl تستخدم الأداة Curl لتحميل الملفات باستخدام سطر أوامر لينكس، أما الحزمة الثانية التي يتم تثبيتها فهي الأهم إذا كانت توزيعة لينكس المستخدمة قديمة بعض الشيء أما إذا كانت التوزيعة حديثة فلا داع لتنفيذ هذا الأمر. تُستخدم هذه الأداة لإجبار نظام تشغيل أوبونتو لاستخدام https بدلًا من http التي تعد البروتوكول الافتراضي. حتى أن دعم https لم يكن أساسيًا وذلك قبل الإصدار 1.5 من الأداة apt وأما بعد هذا الإصدار فلا يوجد داع لتثبيت الحزمة السابقة لأنها أصبحت مدمجة بشكل تلقائي في الأداة. يبين الشكل أدناه أنّ مخازن برمجيات أوبونتو تستخدم البروتوكول http إلا بعضًا منها التي أضافها المستخدم بشكل يدوي. إذا تضيف الحزمة "apt-transport-https" دعم https إلى الأداة apt ومن الطبيعي أن يتساءل المستخدم عن سبب غياب دعم بروتوكول https بشكل مباشر من قبل نظام أوبونتو علمًا أنه أكثر أمانًا من استخدام البروتوكول http وتجيب الفقرة التالية على هذا التساؤل. الجزء الثاني: إضافة مفتاح GPG الخاص بمخزن البرمجيات البعيد تستخدم مخازن برمجيات لينكس آلية حماية تعتمد على مفاتيح GPG المبنية ضمن مخزن البرمجيات. يضيف كل مخزن مفتاحه إلى قائمة المفاتيح الموثوقة الخاصة بمخازن البرمجيات. يتم توقيع الحزم البرمجية باستخدام هذا المفتاح وعند تثبيتها يتم التحقق من مطابقة المفتاح المخزّن لدى نظام التشغيل مع المفتاح المستخدم في عملية التوقيع للتحقق من أن الحزمة قد تم تثبيتها من المخزن البرمجي الصحيح. يظهر خطأ في حال فشل عملية التحقق ولا يثبت النظام الحزمة الجديدة أو لا يحدثها قبل ضمان نجاح عملية التحقق. نضيف في الخطوة التالية مفتاح GPG الخاص بالمخزن البرمجي البعيد إلى قائمة المفاتيح الموثوقة ضمن نظام التشغيل لينكس لكي يصبح قادرًا على الوثوق بالحزم البرمجية القادمة من ذلك المخزن وذلك بتنفيذ الأمر التالي: curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - يحمل الأمر السابق مفتاح GPG من الرابط الذي تمت إضافته، تفيد الراية sS إلى تفعيل النمط الصامت Silent mode حيث لا تظهر على الشاشة المعلومات التي يتم تبادلها أثناء عملية التحميل وتظهر منها الأخطاء فقط. يجب الانتباه إلى وجود الشريطة - في نهاية الأمر فهي المسؤولة على توجيه ما يتم تنزيله في الجزء الأول من الأمر إلى استدعاء الأداة apt-key في الأمر الثاني بدلًا من حفظه كملف. أي تتم إضافة المفتاح بشكل مباشر إلى النظام عبر تنفيذ الأمر apt-key add. يمكن استعراض مفاتيح GPG الخاصة بمخازن البرمجيات مختلفة ضمن نظام التشغيل باستخدام الأمر apt-key list فيظهر خرج مشابه لما يلي: توجد عدة طرق أخرى يمكن استخدامها لإضافة مفاتيح GPG أيضًا كما في الشكل التالي: sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9 يمكن أن يظهر تحذير بأن الأداة apt-key أصبحت قديمة وأنها لن تكون مدعومة بدءًا من الإصدار 22.04 الخاص بتوزيعة أوبونتو ويمكن تجاهل هذا التحذير. الجزء الثالث: إضافة عنوان مخزن البرمجيات البعيد إلى قائمة مصادر التثبيت الموثوقة يضيف الأمر التالي مُدخلًا جديدًا خاصًا بالمخزن الجديد إلى قائمة مصادر التثبيت الموثوقة من قبل نظام التشغيل، وبالتالي يتحقق نظام التشغيل من هذا المخزن عند الحاجة إلى تثبيت حزم جديدة أو تحديث وترقية الحزم القديمة. sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list' يتضمن الملف ‎/etc/apt/sources.list قائمة بعناوين مخازن البرمجيات الخاصة بنظام أوبونتو ويجب على المستخدم ألا يعدل هذا الملف نهائيًا وإنما يجب إنشاء ملف جديد على أن يكون له اللاحقة .list وتخزينه ضمن المجلد ‎/etc/apt/source.list.d كما في الشكل أدناه: تسهل هذه الإضافة عملية إدارة الحزم إذ يكفي عند الرغبة بإزالة مخزن ما من قائمة المصادر الموثوقة أن يتم حذف الملف الموافق من المجلّد السابق وبالتأكيد دون أن يتم تعديل الملف sources.list. بالعودة إلى الأمر السابق، يفيد استخدام sh إلى تشغيل الأمر ضمن نافذة جديدة من الصدفة shell. تفيد إضافة الراية ‎-c لتوجيه الأمر sh إلى قراء الأوامر من المعامل الذي يلي الراية ‎-c بدلاً من مدخلات المستخدم ومن ثم تتم إضافة السطر التالي: deb https://dl.yarnpkg.com/debian/ stable main باستخدام تعليمة echo إلى الملف ‎/etc/apt/sources.list.d/yarn.list الذي يتم إنشاؤه. توجد العديد من الطرق لتنفيذ عملية الإضافة السابقة أيضًا فيمكن الحصول على نفس النتيجة بتنفيذ الأمر التالي: echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list الجزء الرابع: تثبيت التطبيقات من المخزن البرمجي الذي تمت إضافته على الرغم من إضافة مفتاح GPG وعنوان المخزن البرمجي إلا أنّ نظام التشغيل لم يتعرّف على الحزم البرمجية الموجودة لدى هذا المخزن، لهذا يجب تحديث الذاكرة المخبئية cache الخاصة بالأداة apt للتعرف على الحزم البرمجية المتاحة وإصداراتها وذلك بتنفيذ الأمر التالي: sudo apt update يمكن البدء بتثبيت الحزم البرمجية بعد انتهاء تنفيذ الأمر السابق وعليه ننفذ الأمر التالي: sudo apt install yarn يمكن لتوفير الوقت أن يتم دمج الأمرين معًا بالشكل التالي: sudo apt update && sudo apt install yarn يضمن استخدام && أنّ الأمر الثاني لن ينفّذ قبل انتهاء تنفيذ الأمر الأول دون وجود أخطاء، وبهذا تكون قد اكتملت الإجرائية. الخلاصة يضطر معظم مستخدمي لينكس إلى إضافة مصادر تثبيت برمجيات إضافية، لهذا يجب إتقان كيفية إضافة هذه المصادر بشكل آمن إلى قائمة المصادر الموثوقة من قبل نظام التشغيل. تضمن هذا المقال تعريفًا بكيفية إضافة عنوان مخزن برمجي إلى المخازن الموثوقة من قبل نظام التشغيل المستخدم.كما تضمن مثالًا عمليًا لتثبيت حزمة برمجية غير موجودة ضمن مخازن البرمجيات الأساسية الخاصة بنظام تشغيل أوبونتو ترجمة وبتصرف للمقال Installing Packages From External Repositories in Ubuntu [Explained] لصاحبه Abhishek Prakash. اقرأ أيضًا أساسيات إدارة الحزم في أوبنتو ودبيان أساسيات إدارة الحزم: apt ،yum ،dnf ،pkg 10 أدوات مفيدة لمستخدمي لينكس ربما لم تسمع عنها من قبل
  2. يتعامل مستخدمي توزيعة ديبيان Debian وأوبونتو Ubuntu ومينت Mint وجميع مستخدمي توزيعات لينكس المعتمدة على أوبونتو أو ديبيان مع أوامر apt لتثبيت الحزم البرمجية المختلفة. نلاحظ بسهولة أنه ومنذ انطلاقة أوبونتو 16.04 قد شاع استخدام الأمر apt بشكل كبير إضافة إلى التوصية باستخدامها كمدير الحزم البرمجية ضمن نظام لينكس. يتضمن هذا المقال تعريفًا للراغبين بإتقان استخدام نظام لينكس وأدواته المختلفة وتحديدًا أداة تثبيت الحزم البرمجية والتي يضطر جميع المستخدمين الى التعامل معها عاجلًا أم آجلًا. ما هي الأداة apt؟ تمتلك كل توزيعة لينكس نظام تحزيم packaging system خاص بها والذي يتيح التطبيقات والبرامج ليثبتها المستخدم على نظام التشغيل. لا يحتاج المستخدم في كل مرة أن يبني البرنامج انطلاقًا من شيفرة المصدر. تستخدم توزيعة ديبيان نظام تحزيم اسمه dpkg ويمكن للمستخدم الاعتماد على أداة موجه الأوامر APT وهي اختصار للعبارة Advanced Package Tool للتفاعل مع نظام التحزيم الخاص بتوزيعات لينكس المبنية على أساس ديبيان. يمكن استخدام الأمر dpkg مباشرة ولكن يتيح الأمر apt المزيد من الخيارات مثل البحث عن الحزم الجديدة وترقيتها وإزالتها إضافة إلى أنها أكثر ملائمة للمستخدمين. يمكن استخدام الأوامر الخاصة بالأداة APT عن طريق تنفيذ الأمر apt في موجه الأوامر. نجد في العديد من المقالات والمراجع استخدام الأمر apt-get بدلًا من apt وذلك لتثبيت الحزم. شاع استخدام الأمر الأول لفترة طويلة من الزمن إلا أنّ الأمر الثاني قد حل مكانه بسبب بساطته وفعاليته في تنفيذ عمليات تثبيت الحزم. تحديث قاعدة بيانات الحزم باستخدام apt نستخدم في هذا المقال توزيعة أوبونتو 16.04 ولكن يمكن استخدام أية توزيعة لينكس معتمدة على أوبونتو أو ديبيان مثل مينت Mint و لايت Lite وغيرها. تستخدم الأداة apt قاعدة بيانات تتضمن الحزم المتاحة وفي حال عدم تحديث محتوى قاعدة البيانات هذه بشكل دوري فلن تعرف الأداة بأنّ إصدارات حديثة من الحزم أصبحت متاحة ولهذا يجب أن نبدأ العمل أولًا بتحديث قاعدة البيانات هذه بعد تثبيت نظام التشغيل لينكس لأول مرة. يتطلب هذا التحديث استخدام مستخدم ذي صلاحيات مناسبة Superuser ولهذا نستفيد من الأمر sudo بالشكل التالي: sudo apt update يظهر بعد تنفيذ هذا الأمر معلومات الحزم المتاحة والتي يتم الحصول عليها من عدة خوادم موزعة على أماكن جغرافية متعددة كما في الشكل التالي: نلاحظ من الشكل السابق أن معظم الأسطر التي تتعلق بالاتصال بالخوادم تبدأ بأحد الاحتمالات التالية: الإصابة Hit: يشير إلى أنّه لا يوجد تعديل بنسخة الحزمة الموجودة لدى الخادم والنسخة المثبتة على الحاسب التجاهل Ign: يشير إلى أنّه يجب تجاهل هذا التحديث إما لأنه لا يزال حديثًا وبالتالي يتم تأجيل تنفيذ هذا التحديث حتى يثبت استقرار التحديث الجديد أو أنه قد حدث خطأ ما أثناء طلب التحديث ولكن لا يمثّل هذا الخطأ خطورة ويمكن تجاهله. الجلب Get: يشير إلى أنّه تم اكتشاف إصدار أحدث وسيتم تنزيل المعلومات عن الحزم لكي يتم تثبيتها لاحقًا ويظهر في آخر السطر حجم المعلومات التي يتم تحميلها. ترقية الحزم المثبّتة باستخدام الأداة apt يمكن بعد تحديث قاعدة بيانات الحزم البدء بترقية الحزم المثبّتة على الحاسب، من المفضل أن تتم هذه الترقية بشكل دوري لجميع الحزم نظرًا لأن عمليات الترقية تحدث لحل مشاكل برمجية معينة أو لتحسين الأداء. نبدأ عملية الترقية باستخدام الأمر: sudo apt upgrade تظهر بعدها معلومات عن الحزم التي سيتم ترقيتها من حيث عدد هذه الحزم والحجم الكلي الذي سيتم تحميله من الإنترنت وكم يبلغ الحجم الإضافي الذي سيتم استهلاكه من الحاسب كما في الشكل التالي: يمكن أيضًا أن تتم عملية الترقية للحزم بتنفيذ أمر آخر على الشكل التالي: sudo apt full-upgrade يعمل هذا الأمر كسابقه إلا أنّه يثبت التحديثات المتعلّقة بترقية النظام والتي تتطلب إزالة حزمة موجودة على نظام التشغيل أما الأمر السابق فلا يستطيع تنفيذ مثل هذه العملية. ما الاختلاف بين الأمر apt update والأمر apt upgrade؟ يجب التذكر دومًا أنّ الأمر apt update يحدّث قاعدة بيانات الحزم فقط ولا يرقّي الحزم فعليًا. لنفرض أنه توجد حزمة مثبّتة على الحاسب الشخصي اسمها XYZ وكان الإصدار المثبت 1.3 فبعد تنفيذ الأمر apt update يتم تحديث قاعدة البيانات لتشير إلى الإصدار 1.4 المتاح للتثبيت، يمكن عندها تنفيذ الأمر apt upgrade لترقية الحزمة المطلوبة للإصدار الأحدث. يمكن دمج هذين الأمرين لتسريع هذه العملية بالشكل التالي: sudo apt update && sudo apt upgrade -y تثبيت الحزم الجديدة باستخدام الأداة apt يستخدم الأمر لتثبيت الحزم الجديدة التي يحتاجها المستخدم في عمله بالشكل التالي: sudo apt install <package_name> نضيف اسم الحزمة المطلوبة بدلًا من فعلى سبيل المثال يمكن من أجل تثبيت الحزمة mplayer تنفيذ الأمر التالي: sudo apt install mplayer يظهر عندها خرج مشابه للشكل التالي: تعد ميزة الإكمال التلقائي مفيدة جدًا عند عدم معرفة اسم الحزمة بشكل كامل وخصوصًا أن بعض الحزم يكون اسمها كبيرًا بعض الشيء. نكتب بضعة حروف من اسم الحزمة ومن ثم يمكن الضغط على مفتاح تاب tab ليتم اقتراح مجموعة الحزم المتاحة والتي تبدأ بالحروف التي تم إدخالها بالشكل التالي: تثبيت عدة حزم معًا باستخدام الأداة apt يمكن تثبيت دفعة من الحزم معًا وذلك في حال كان عدد الحزم المطلوبة للتثبيت كبيرًا فمن غير المجدي أن يتم تثبيتها واحدة تلو الأخرى. يتم ذكر اسم الحزم بشكل متتالي بحيث يفصل بينها فراغ واحد كما في الشكل التالي: sudo apt install <package_1> <package_2> <package_3> تنفيذ الأمر apt على حزمة مثبّتة بشكل مسبق يتم في هذه الحالة ترقية هذه الحزمة في حال وجود إصدار أحدث ضمن قاعدة البيانات ولا يسبب ذلك أية مشكلة إلا في حال عدم رغبة المستخدم أن يرقّي الحزمة لسبب ما. تثبيت الحزم دون تنفيذ عملية الترقية يمكن تثبيت حزمة ما دون الحاجة إلى تنفيذ أمر الترقية في حال رغب المستخدم بذلك عبر إضافة الخيار ‎--no-upgrade بالشكل التالي: sudo apt install <package_name> --no-upgrade يظهر عندها الخرج بالشكل التالي: ترقية حزمة موجودة دون تثبيتها في حال لم تكن مثبتة يمكن ترقية حزمة موجودة في حال وجودها بشكل مسبق على الحاسب دون أن يتم تثبيتها تلقائيًا في حال لم تكن مثبّتة بإضافة الخيار ‎--only-upgrade بالشكل التالي: sudo apt install <package_name> --only-upgrade يظهر عندها الخرج بالشكل التالي: تثبيت إصدار محدد من حزمة يتم اختيار النسخة الأحدث والأكثر استقرارًا للحزمة عند طلب المستخدم لتثبيتها بشكل افتراضي ولكن تظهر بعض الحالات التي يحتاج فيها المستخدم نسخة محددة من حزمة ما. يعد مثل هذا الشرط ضروريًا عند تجهيز وتثبيت بعض أنواع الخدمات والتي قد تشترط وجود حزمة بإصدار معين لكي تعمل بشكل صحيح حيث أنّها لا تكون متوافقة مع النسخ الأحدث. نستطيع تحقيق بالشكل التالي: sudo apt install <package_name>=<version_number> إزالة الحزم المثبّتة على باستخدام الأداة apt يستخدم الأمر apt أيضًا لإزالة الحزم المثبتة على الحاسب أيضًا، يتم ذلك بالشكل التالي: sudo apt remove <package_name> يظهر خرج مشابه للشكل التالي: يمكن الاستفادة من الإكمال التلقائي في استعراض الحزم المثبّتة وذلك بشكل مماثل لما قمنا به مسبقًا إذ يكفي كتابة بضعة أحرف من اسم الحزمة والضغط على المفتاح تاب tab ليتم عرض قائمة بالحزم المتاحة. يمكن إزالة الحزم أيضًا باستخدام الأمر purge وذلك بالشكل التالي: sudo apt purge <package_name> يحذف هذا الأمر كل ما يتعلق بالحزمة من ملفات إعداد وغيرها بينما يبقى الأمر remove على بعض ملفات الإعداد ضمن النظام إذ يعد ذلك مفيدًا في حال حذف المستخدم حزمة ما ورغب الاحتفاظ بالإعدادات التي نفّذها في حال رغبته بتثبيتها لاحقًا. أما الأمرpurge فيعد مناسبًا عندما يتم إتلاف ملفات الإعداد بشكل نهائي لا رجعة فيه وعندها يعد خيار إزالة كل ما يتعلق بالحزمة وتثبيته من البداية هو الأفضل. يتم عادة استخدام apt remove أكثر من الأمر apt purge لأن المستخدم لا يحتاج إلى تعديل إعدادات الحزم بشكل كبير. البحث عن الحزم في لينكس يمكن البحث عن حزمة محددة بكل بساطة باستخدام الأمر apt search ليتم عرض جميع الحزم التي تتضمن مصطلح البحث الذي تم إدخاله وذلك بتنفيذ الأمر: apt search <search term> ليظهر عندها الخرج بالشكل التالي: استعراض محتوى حزمة في لينكس نستعرض محتوى حزمة ما قبل إزالتها أو تثبيتها بتنفيذ الأمر التالي: apt show <package_name> تظهر عندها العديد من المعلومات المتعلقة بالحزمة مثل توصيف الحزمة واسم الحزم التي تعتمد عليها هذه الحزمة إضافة إلى رقم الإصدار الخاص بها وغيرها من المعلومات المهمة والتي يبينها الشكل التالي: استعراض قائمة الحزم الجاهزة للترقية وإصداراتها الحالية يمكن استعراض قائمة الحزم المثبّتة على الحاسب والتي يمكن ترقيتها إلى إصدار أحدث. يعد هذا الخيار مهمًا جدًا عندما يتم ترقية مجموعة من الحزم والتي تعتمد على بعضها بحيث نهتم برقم الإصدار الحالي ورقم الإصدار الجديد. نحصل على هذه القائمة بتنفيذ الأمر التالي: apt list --upgradable ليظهر عندها الخرج بالشكل التالي: كما نستطيع استعراض قائمة الحزم المثبّتة فقط على الحاسب وذلك بتنفيذ الأمر التالي: apt list --installed كما نستطيع استعراض قائمة التطبيقات المثبتة بجميع الإصدارات الموجودة على الحاسب، يعد هذا الأمر بالغ الأهمية للعودة إلى إصدار قديم من حزمة محددة كانت تعمل بشكل صحيح. نستعرض هذه القائمة بتنفيذ الأمر التالي: apt list --all-versions تنظيف النظام باستخدام الأداة apt نستخدم الأمر apt autoremove لإزالة أية حزم لم يعد هنالك حاجة لوجودها ضمن الحاسب إضافة لإزالة أية مكتبات برمجية أصبحت بلا فائدة والتي تستهلك مساحة تخزينية عند بقائها ضمن النظام. يتم ذلك بتنفيذ الأمر التالي: sudo apt autoremove لنحصل بعدها على الخرج التالي: الخاتمة تضمن هذا المقال تعريفًا بالأداة apt وتوضيحًا للخيارات العديدة التي يمكن الاستفادة منها في تثبيت الحزم وإدارتها. تعد هذه الأداة أساسية لجميع مستخدمي نظام لينكس والذين قد اختاروا توزيعات مبنية على أوبونتو أو ديبيان. ترجمة وبتصرف للمقال Using apt Commands in Linux [Complete Guide] لصاحبه Abhishek Prakash. اقرأ أيضًا ما هو نظام التشغيل لينكس؟ عشرون أمرا في لينكس يفترض أن يعرفها كل مدير نظم أساسيات إدارة الحزم: apt ،yum ،dnf ،pkg
  3. تتراكم البرامج والملفات الخاصة بالمستخدمين مع الزمن ضمن أي نظام تشغيل وحتى عندما يقوم المستخدم بإزالة بعض البرامج فقد تبقى عدة ملفات عالقة للأبد ضمن ملفات نظام التشغيل. يمكن للمستخدم الذي يمتلك مساحات تخزينية تفوق التيرا بايت Tera Byte أن يتجاهل هذه التراكمات، أما المستخدم الذي يمتلك قرصًا صلبًا من نوع SSD والذي يكون عادة بسعات منخفضة فقد يضطر إلى إزالة هذه التراكمات بشكل دوري. يتضمن هذا المقال أبسط الطرق الذي يستطيع المستخدم تنفيذها لتحرير المساحة ضمن توزيعة أوبونتو Ubuntu ويجب على المستخدم مراقبة المساحة الحرة ضمن جهازه باستمرار ليختار الوقت المناسب لتحرير المساحة. فحص المساحة الحرة ضمن توزيعة أوبونتو يستطيع المستخدم التحقق من المساحة الحرة المتبقية على حاسبه الشخصي باستخدام أداة تحليل استخدام القرص Disk Usage Analyzer المتاحة بشكل افتراضي ضمن توزيعة أوبونتو. يمكن البحث عن هذه الأداة ضمن القائمة الرئيسية وبعد تشغيلها يظهر القرص الصلب والمساحة الحرة المتبقية. يستطيع المستخدم البدء بتحرير المساحة عندما تبلغ المساحة المتبقية من القرص الحد الذي يراه مناسبًا ويمكن بعد الانتهاء من عملية التحرير إعادة تفقد المساحة باستخدام نفس الأداة. تحرير مساحة القرص ضمن توزيعتي أوبونتو و لينكس مينت توجد عدة طرق لتحرير مساحة القرص الصلب ضمن توزيعة أوبونتو أو أنظمة التشغيل المبنية على أوبونتو. منها ما يكون عن طريق تنفيذ الأوامر النصية ومنها ما يكون متاحًا باستخدام أدوات ذات واجهات رسومية. تجدر الإشارة إلى أنه من الأفضل أن يتجنب المستخدم العادي تنفيذ بعض العمليات التي لا يتقنها بشكل جيد تجنبًا لأية ضرر يمكن أن يصيب الحاسب. يتم الاعتماد على نسخة أوبنتو 16.04 في هذا المقال ولكن تبقى الخطوات ذاتها من أجل أوبونتو 18.04 وإصدارات أوبونتو المختلفة كما تنطبق هذه التعليمات على الأنظمة المعتمدة على أوبونتو مثل مينت وغيرها. 1. التخلص من الحزم غير المستخدمة قد تحتاج حزمة ما يقوم المستخدم بتثبيتها إلى تثبيت مجموعة من الحزم الضرورية لعملها، تظهر مشكلة عندما يتم إزالة هذه الحزمة دون أن تتم إزالة الحزم المرتبطة بها مما يؤدي إلى تراكمها واستهلاكها لمساحة تخزينية دون جدوى. وجدنا في [نضع هنا رابط المقالة رقم 7](رابط المقالة رقم 7) أنه يمكن استخدام الأمر apt-get الذي يستخدم لتثبيت الحزم من أجل إزالة الرزم عن طريق الأمر autoremove والذي يزيل هذه الرزم العالقة كما أنه يزيل أي نسخ قديمة من نواة نظام التشغيل لينكس والتي يمكن أن تصبح بلا فائدة بعد ترقية النظام. يتم ذلك عبر تنفيذ الأمر التالي في موجه الأوامر وبالطبع فإننا نحتاج إلى صلاحيات مناسبة لتنفيذ عمليات الحذف هذه: sudo apt-get autoremove يظهر الشكل أدناه أنه سيتم تحرير مساحة تعادل 300 ميغابايت من القرص الصلب بعد نجاح تنفيذ هذه العملية ويمكن أن تكون هذه المساحة أكبر وذلك تبعا لطريقة استخدام الحاسب والفترة الزمنية المنقضية منذ آخر عملية تحرير مساحة تم تنفيذها. 2. إزالة التطبيقات غير الضرورية توجد العديد من التطبيقات الموجودة بشكل افتراضي ضمن توزيعة أوبونتو، وقد تمر سنين دون أن يستخدمها أحد وخصوصًا الألعاب وبعض التطبيقات الإضافية وبالتالي يمكن إزالتها. كما ينطبق ذلك على بعض التطبيقات التي ثبّتها المستخدم واستخدمها مرة واحدة ونسي استخدامها أو أنه لم يعد بحاجتها لذلك يجب إزالة هذه التطبيقات إما بالاعتماد على مركز البرمجيات Software Center أو باستخدام موجه الأوامر وتنفيذ الأمر التالي: sudo apt-get remove package-name1 package-name2 3. تنظيف الذاكرة المخبئية Cache الخاصة بالأداة APT تستخدم توزيعة أوبونتو الأداة APT من أجل تثبيت وإدارة وإزالة الحزم البرمجية. تحتفظ هذه الأداة بنسخة من الحزم البرمجية التي تم تحميلها وتثبيتها مسبقًا حتى بعد أن تتم إزالة هذه الحزم البرمجية من النظام. يتم تخزين هذه الحزم ضمن المسار ‎/var/cache/apt/archives. يزداد حجم هذا المجلّد مع الزمن ويمكن التحقق من حجمه عبر تنفيذ الأمر: sudo du -sh /var/cahce/apt يظهر الشكل أنه تم إشغال حوالي 500 ميغابايت من القرص في المجلّد السابق ويجب تحرير هذه المساحة. يمكن تحرير هذه المساحة بطريقتين، إما عن طريق إزالة الرزم التي أصبحت قديمة جدًا والتي لا يمكن إعادة استخدامها بعد اعتماد تحديث ما مما يجعلها بلا قيمة ويتم ذلك بتنفيذ الأمر: sudo apt-get autoclean أو عبر حذف كامل هذه المساحة التخزينية مما يوفر الكثير من المساحة ولكنه قد يجبر المستخدم على تنزيل بعض الحزم البرمجية في حال احتاجها مرة ثانية في حال لم تكن هذه الحزم قديمة ويتم ذلك بتنفيذ الأمر: sudo apt-get clean 4. تفريغ ملفات السجلات ملاحظة: هذه الخطوة تتطلب معرفة متقدمة. تتضمن جميع توزيعات لينكس آليات تسجيل لحفظ جميع العمليات والقيم التي تتغير ضمن النظام. نجد سجلًا خاصًا بنواة نظام التشغيل وسجلًا خاصًا برسائل النظام وسجلًا يحتوي على الأخطاء الخاصة بجميع الخدمات التي تعمل ضمن نظام لينكس سواء كانت من ضمن نظام التشغيل أو أن المستخدم ثبتها على النظام. يزداد حجم هذه السجلات بسرعة كبيرة، إذ تسجّل هذه القيم دون توقف مما يجعل حجم هذه السجلات كبيرًا ويمكن الاطلاع على هذا الحجم عن طريق تنفيذ: journalctl --disk-usage تجدر الإشارة إلى أنه على عكس الحزم فلا يجب حذف جميع السجلات ويجب الاحتفاظ ببعضها لذلك من الشائع أن يحتفظ المستخدم بالسجلات التي لم يمض عليها زمن طويل، يتم تنفيذ الأمر أدناه لإزالة السجلات التي تتضمن المعطيات المتعلقة بالأداء منذ أكثر من ثلاث أيام: sudo journalctl --vacuum-time=3d يظهر الخرج أدناه بعد تنفيذ الأمر السابق: abhishek@itsfoss:~$ journalctl --disk-usage Archived and active journals take up 1.8G in the file system. abhishek@itsfoss:~$ sudo journalctl --vacuum-time=3d Vacuuming done, freed 1.7G of archived journals from /var/log/journal/1b9ab93094fa2984beba73fd3c48a39c 5. إزالة النسخ القديمة من التطبيقات المثبّتة باستخدام مدير الحزم Snap ملاحظة: هذه الخطوة تتطلب معرفة متقدمة. يتيح مدير الحزم Snap الكثير من التطبيقات التي تفيد المستخدمين ولهذا يكون لها شعبية كبيرة مقارنة بمدراء الحزم التقليديين، تكمن المشكلة الأساسية أنّ الحزم المثبّتة عن طريق مدير الحزم Snap تكون أكبر حجمًا من غيرها ومما يزيد من حجم المشكلة أن مدير الحزم Snap يحتفظ بنسختين على الأقل من نفس الحزمة التي يتم تثبيتها وذلك في حال رغب المستخدم العودة إلى نسخة أقدم من نفس الحزمة، نستعرض المساحة التي تستهلكها هذه الأداة عبر تنفيذ الأمر التالي ويظهر الخرج المبين أدناه بعد تنفيذها du -h /var/lib/snapd/snaps 4.0K /var/lib/snapd/snaps/partial 5.6G /var/lib/snapd/snaps نلاحظ أن المساحة المشغولة وصلت إلى خمسة غيغابايت وهذه المساحة كبيرة نسبيًا. مع تفاقم هذه المشكلة عمد أحد المطورين العاملين ضمن فريق تطوير مدير حزم Snap وهو آلان بوب إلى تطوير سكربت Script بسيط يزيل النسخ القديمة من التطبيقات المثبّتة باستخدام مدير الحزم Snap. ننشئ ملف نص برمجي ونضع فيه المحتوى التالي: #!/bin/bash # Removes old revisions of snaps # CLOSE ALL SNAPS BEFORE RUNNING THIS set -eu snap list --all | awk '/disabled/{print $1, $3}' | while read snapname revision; do snap remove "$snapname" --revision="$revision" done يجب إضافة الصلاحيات التنفيذية المناسبة لملف النص البرمجي السابق وتشغيله مع صلاحيات مدير باستخدام sudo. يتم تحرير المساحة المحجوزة التي يمكن تحريرها ونستعرض المساحة بنفس الطريقة السابقة ليكون الخرج بالشكل التالي: du -h /var/lib/snapd/snaps 4.0K /var/lib/snapd/snaps/partial 2.5G /var/lib/snapd/snaps فصلنا أكثر عن هذه الخطوة في مقال مسح حزم Snap المعطلة لتحرير المساحة في لينكس. 6. إزالة الذاكرة الوسيطة الخاصة بالصور المصغّرة thumbnail ملاحظة: هذه الخطوة تتطلب معرفة متقدمة. تنشئ توزيعة أوبونتو صور مُصغَّرة خاصة بالعرض ويخزنها في مجلّد مخفي ضمن المساحة التخزينية الخاصة بالمستخدم وهو ‎~/.cache/thumbnails. يزداد عدد هذه المصغّرات مع الزمن وبالتالي يزداد حجمها مع العلم بأن بعض هذه المصغرات تعود لصور لم تعد موجودة ولهذا يجب إزالتها. يمكن التحقق من حجم الذاكرة الوسيطة الخاصة بالمصغرات عبر تنفيذ الأمر التالي: du -sh ~/.cache/thumbnails يبين الشكل التالي نتيجة تنفيذ هذا الأمر: يفضل تحرير هذه المساحة كل بضعة أشهر ويمكن ذلك بتنفيذ الأمر التالي: rm -rf ~/.cache/thumbnails/* 7. إيجاد وحذف الملفات المتكررة يمكن أن تتكرر الملفات دون إدراك المستخدم وفي حال كانت هذه الملفات ذات حجوم كبيرة كملفات الفيديو أو الصور عالية الدقة فسوف يستهلك ذلك مساحة كبيرة ولهذا يمكن البحث عن هذه الملفات المكررة وإزالتها. يمكن تنفيذ ذلك باستخدام الأداة ذات الواجهات الرسومية FSlint أو باستخدام الأداة FDUPES التي تعمل ضمن موجه الأوامر والتي يبين الشكل أدناه مثالًا على عملها. يمكن للخبراء تنفيذ بعض الخطوات الإضافية لتحرير المزيد من المساحة، ولا يعني ربط الخطوات التالية بالخبراء أن المستخدم العادي لا يجب أن يحاول تنفيذ هذه الخطوات ولكن من الأفضل أن يكون حذرًا وأن يحتفظ بنسخة احتياطية لملفاته المهمة. 8. إزالة نوى لينكس القديمة التي تم تثبيتها بشكل يدوي ملاحظة: هذه الخطوة تتطلب خبرة متقدمة. ناقشنا في الخطوة رقم 1 السابقة استخدام أمر لإزالة نواة نظام لينكس القديمة ولكن يجب الانتباه أنّ هذا الأمر لا يزيل نواة لينكس التي يثبتها المستخدم بشكل يدوي وإنما فقط يزيل ما ثبّته النظام تلقائيًا. تحرر عملية الإزالة هذه الكثير من المساحة وللتحقق من وجود هذه النوى على الجهاز يمكن تنفيذ الأمر التالي: sudo dpkg --list 'linux-image*' لا تختلف إزالة نواة نظام التشغيل عن إزالة أية حزمة برمجية، فبعد أن يظهر الأمر السابق النوى المتاحة يتم تسجيل رقم الإصدار VERSION الذي يجب إزالته وننفذ الأمر التالي: sudo apt-get remove linux-image-VERSION يوصي الخبراء أن يحافظ المستخدم على نسختين أو ثلاث من نوى نظم التشغيل ومن ضمنه أحدث نسخة للنواة مما يتيح العودة إلى نسخة أقدم من النواة في حال ظهور مشكلة ضمن النواة الجديدة. 9. إزالة الحزم اليتيمة ملاحظة: هذه الخطوة تتطلب خبرة متقدمة. نعرّف الحزم اليتيمة على أنّها الحزم التي يتم تثبيتها ضمن النظام لكونها متطلّبًا لحزمة أساسية أخرى وقد حذف المستخدم هذه الخدمة الأساسية وبقيت الحزمة اليتيمة ضمن النظام. وجدنا في الخطوة رقم 1 أنه يمكن تنفيذ أمر لإزالة هذه الحزم ولكن تكمن المشكلة الأساسية إذا ثبت المستخدم هذه الحزم المكمّلة لحزمة ما بشكل يدوي وبالتالي لن يستطيع الأمر السابق إزالتها لأنه لا يستطيع الجزم بأن المستخدم ثبت هذه الحزمة لحاجته لها أم أنها كانت متطلّبًا لحزمة أخرى فيضطر إلى تجاوزها. يجب أن يبحث المستخدم عن هذه الحزم بشكل يدوي ولكن لحسن الحظ توجد عدة أدوات منها ما يمتلك واجهات رسومية مثل gtkorphan والتي تساعد في العثور على الحزم اليتيمة. يتم تثبيت هذه الأداة بتنفيذ الأمر التالي: sudo apt-get install gtkorphan يبين الشكل التالي الواجهة الأساسية للأداة وتجدر الإشارة إلى أنّ المستخدم لا يحتاج لهذه الأداة فعليًا إلا إذا كان بحاجة كل المساحة التخزينية المتاحة لسبب ما. ملاحظة: قد لا تكون الحزمة gtkorphan متوفرة أثناء قراءة المقال، لذا يمكنك استعمال البديل المناسب والمريح لك، مثل deborphan وغيرها. 10. استخدام الأدوات ذات الواجهات الرسومية لتحرير المساحة في أوبونتو توجد عدة سكربتات تستخدم لتحرير المساحة ضمن توزيعة أوبونتو وقد تم ذكر البعض منها كما توجد المزيد منها ما لم تشمله هذا المقال. يصبح تذكر الأوامر صعبًا لدى بعض المستخدمين ولهذا يمكن استخدام الأدوات ذات الواجهات الرسومية وتعد الأداة Stacer واحدة من أهم هذه الأدوات والتي تتسم بسهولة الاستخدام. الخاتمة تضمنت المقالة بعض الخطوات الأساسية لتحرير المساحة ضمن توزيعة أوبونتو والأنظمة المعتمدة عليها، حيث أنّ بعض هذه الخطوات بسيطة ويجب على جميع المستخدمين تنفيذها بشكل دوري ومنها ما يتطلب أنْ يكون المستخدم خبيرًا ويمكن تجنبها لوقت الحاجة الفعلية للمساحة ويترك تقدير ذلك للمستخدم وحاجته الفعلية للمساحة. ترجمة وبتصرف للمقال ‎7 Simple Ways to Free Up Space on Ubuntu and Linux Mint لصاحبه Abhishek Prakash. اقرأ أيضًا التعرف على اختناقات الأداء في نظام لينكس باستخدام الأدوات مفتوحة المصدر كيفية تثبيت التطبيقات في لينكس كيف تفهم هيكلية نظام الملفات في لنكس
  4. يعد نظام Flatpak بأنه نظام تحزيم عالمي جديد يتيح صيغة format جديدة لتثبيت التطبيقات ضمن توزيعات لينكس بسهولة. يمكن تثبيت التطبيقات ضمن نظام لينكس بعدة طرق، وأسهل هذه الطرق استخدام مركز البرمجيات Software Center للبحث عن التطبيق وتثبيته، أما التطبيقات غير الموجودة في المركز فيمكن أن يتم تثبيتها باستخدام حزم RPM أو DEB. أما بالنسبة لتوزيعات ديبيان والتوزيعات المبنية عليها فتستخدم حزم PPA للحصول على التطبيقات، وبشكل عام يمكن بناء أي تطبيق من الرماز المصدري الخاص به والمتاح حتمًا إذا كان التطبيق جاهزًا للعمل ضمن نظام تشغيل لينكس. توجد العديد من المشاكل التي يمكن أن تظهر عند استخدام الطرق السابقة، فمركز البرمجيات ومخازن تثبيت التطبيقات عمومًا قد لا تمتلك أحدث نسخة من التطبيق المطلوب. كما أن التعامل مع الحزم الضرورية لعمل تطبيق ما وتثبيتها بشكل صحيح يمكن أن يكون متعبًا في بعض الحالات، كما أن بعض الملفات المستخدمة في تثبيت البرمجيات يمكن أن تكون خطرة أما بناء التطبيق انطلاقًا من رماز المصدر الخاص به قد يكون صعبًا بالنسبة لبعض المستخدمين. ظهرت الحاجة إلى وجود نظام تحزيم عالمي بسبب الأسباب السابقة ومع ازدياد عدد وتنوع توزيعات لينكس بحيث يكون هذا النظام الجديد قادرًا على تثبيت وتشغيل التطبيق بغض النظر عن التوزيعة المستخدمة. طوّرت مجموعة Canonical نظام Snap لإيجاد حل لهذه المشاكل كما أن بعض المطورين المستقلين طوروا نظام تحزيم مستقل وأسموه AppImage والذي يحمّل التطبيق ويشغله دون تثبيته فعليًا على الحاسب. يوجد إلى جانب هذين النظامين نظام تحزيم عالمي مميز اسمه Flatpak والذي يمكن استخدامه على معظم توزيعات لينكس. ما هو نظام Flatpak؟ نعرّف نظام Flatpak على أنه إطار عمل للتطبيقات ضمن نظام التشغيل لينكس بغض النظر عن التوزيعة المستخدمة. يهدف نظام Flatpak إلى توفير حلول لمشاكل تثبيت التطبيقات مستقلة عن منصة العمل بالإضافة إلى العديد من المزايا الأخرى مما يسهل العمل على المطورين بحيث يكفي تطوير التطبيق مرة واحدة واستخدامه على جميع توزيعات نظام لينكس -التي تدعم نظام Flatpak- دون الحاجة إلى إيجاد طريقة للتثبيت لتناسب كل توزيعة على حدى. المزايا الأساسية لنظام Flatpak: يقدم هذا النظام واجهة موحّدة لتوزيعات لينكس المختلفة، ويضاف إلى ذلك إمكانية دمجه بالتوزيعات المختلفة بسهولة إذ يمكن تثبيت هذا النظام مباشرة من مراكز البرمجيات الخاصة بكل توزيعة فمثلًا يمكن تثبيت النظام Flatpak من ضمن مركز برمجيات Gnome ضمن أية توزيعة لينكس تستخدمه. تتميز تطبيقات Flatpak بأنها متوافقة مع النسخ التالية أيْ أنّ التطبيق يكون مناسبًا للاستخدام ضمن الإصدار التالي من التوزيعة دون تنفيذ أية تغييرات. الحفاظ على الحزم المتعلقة بالحزمة الأساسية بزمن التشغيل حيث تتم إضافة هذه الحزم وكأنها جزء من التطبيق. على الرغم من أنّ نظام Flatpak يتيح توزيع التطبيقات بشكل مركزي إلا أنّه يدعم أيضًا التوزيع اللامركزي للتطبيقات أيضًا. تفعيل دعم نظام Flatpak لتوزيعات لينكس المختلفة تنقسم عملية تثبيت نظام Flatpak إلى خطوتين أساسيتين، ففي الخطوة الأولى يتم تثبيت النظام flatpak وفي الخطوة الثانية يُضاف مخزن برمجيات Flatpak والذي يسمّى باسم Flathub إلى قائمة مصادر البرمجيات مما يسمح باستخدامه لتثبيت التطبيقات. تثبيت Flatpak على أوبونتو Ubuntu ولينكس مينت Mint يتم تثبيت النظام بتنفيذ الأمر التالي: sudo apt install flatpak تثبيت Flatpak على توزيعات ريدهات Red hat يتم تثبيت النظام بتنفيذ الأمر التالي: sudo yum install flatpak تثبيت Flatpak على توزيعة openSUSE يتم تثبيت النظام بتنفيذ الأمر التالي: sudo zypper install flatpak تثبيت Flatpak على توزيعة آرتش Arch Linux يتم تثبيت النظام بتنفيذ الأمر التالي: sudo pacman -S flatpak حل مشكلة تثبيت النظام Flatpak يمكن في حال قد صادفت المستخدم مشكلة شبيهة بما يلي: error: runtime/org.freedesktop.Platform/x86_64/1.6 not installed أن تحل هذه المشكلة بتنفيذ الأمر التالي: flatpak update -v إذ أن هذه المشكلة تحدث بسبب عدم اكتمال التثبيت لسبب ما سواء كان اتصال الانترنت غير مستقرًا أو أنه قد تم إطفاء الحاسب لسبب ما. تحل هذه المشكلة عادة بتحديث قائمة مخازن برمجيات Flatpak عن طريق تنفيذ الأمر السابق. تفعيل دعم نظام Flatpak ضمن مركز البرمجيات تدار تطبيقات Flatpak بشكل كامل باستخدام الأوامر النصية، ولكن يفضل العديد من المستخدمين الواجهات الرسومية بدًلا من كتابة الأوامر وهنا تبرز أهمية نظام Flatpak. نجد نظام Flatpak مدمجًا بشكل مسبق ضمن العديد من توزيعات لينكس ولهذا لا يحتاج المستخدم تنفيذ أية عملية إضافية. أما في التوزيعات التي لا تتيح هذا الدعم بشكل مسبق فيجب تثبيت إضافة Gnome لتثبيت Flatpak باستخدام الواجهات الرسومية. ننفذ الأمر التالي لتحقيق ذلك ضمن توزيعة أوبونتو والتوزيعات المعتمدة عليها: sudo apt install gnome-software-plugin-flatpak أما في حالة التوزيعات الأخرى، فيجب استبدال مدير الحزم المستخدم في الأمر السابق فقط. نعيد تشغيل الحاسب أو خدمة مركز البرمجيات حسب ما يفضّله المستخدم. نحمل الملف الذي يملك اللاحقة ‎.flatpakref من الموقع الخاص بمطور التطبيق أو من موقع المتجر الرسمي لتطبيقات Flatpak. ننتقل إلى مجد التحميل وننقر مرتين على الملف لتظهر واجهة مركز البرمجيات والتي تحتوي خيارات التثبيت كما تظهر الصورة أدناه: يمكن أيضًا الضغط على الزر اليميني على الملف واختيار فتح الملف باستخدام مثبت البرمجيات الافتراضي (open with software install (default وذلك في حال لم تنجح عملية النقر المزدوج على الملف. نشغّل مركز البرمجيات بعد انتهاء التثبيت من قائمة التطبيقات ويكون النظام Flatpak جاهزًا للاستخدام. استخدام أوامر نظام Flatpak: مخصص للمستخدمين المتقدمين والخبراء يفضّل المستخدم الخبير الأوامر النصية عبر سطر الأوامر لأنها تتيح التحكم الكامل بالأدوات المختلفة. ملاحظة: تجدر الإشارة إلى أنّ الجزء التالي من المقال مخصص للمستخدمين الخبراء الذين يفضلون استخدام الأوامر على الواجهات الرسومية. إضافة مخازن البرمجيات من أجل تثبيت التطبيقات عن طريق Flatpak يحتاج استخدام نظام Flatpak وجود معلومات عن مخازن البرمجيات التي يتم استخدامها لتحميل التطبيقات. يجب إضافة مخزن Flathub إذ أنّه يتيح تثبيت عدد كبير من التطبيقات التي تهم جميع المستخدمين. تجدر الإشارة إلى أنّ مخزن البرمجيات هذا يعد الأكثر استخدامًا لغاية كتابة المقالة ولهذا تم استخدامه ويمكن للمستخدم الذي يفضّل مخزنًا آخرًا أن يستبدل اسم المخزن فقط في الأوامر التالية. نبدأ بإضافة المخزن البرمجي بتنفيذ الأمر التالي: flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo يمكن أن نجد أيضًا العديد من المخازن البرمجية المتاحية ويستطيع المستخدم إضافتهم إذا رغب بذلك. البحث عن حزمة ما باستخدام موجه الأوامر ضمن Flatpak يمكن البحث عن التطبيقات المتاحة عن طريق النظام Flatpak بتنفيذ الأمر التالي: flatpak search applicationname يجب أن يتطابق اسم التطبيق الذي يدخله المستخدم مع اسم التطبيق الفعلي وإلا فلن تظهر نتيجة البحث. تبين الصورة أدناه نتيجة البحث عن أحد التطبيقات الشهيرة: تظهر نتيجة البحث السابقة حقلين أساسيين لعملية تثبيت التطبيقات وهما معرف التطبيق "Application ID" وقائمة المخازن"Remotes". تثبيت تطبيقات Flatpak عبر سطر الأوامر يتم تثبيت تطبيقات Flatpak عن طريقة تنفيذ أمر من الشكل التالي: flatpak install <remotes> <ApplicationID> فمن أجل المثال السابق ننفذ الأمر التالي: flatpak install flathub org.libreoffice.LibreOffice تبدأ عندها عملية التثبيت كما في الشكل التالي: يتيح بعض مطوري التطبيقات مخزن البرمجيات الخاص بهم وعندها يمكن استخدام المسار الكامل لملف flatpakref الخاص بالتطبيق من أجل تثبيت التطبيقات كما يلي: flatpak install --from https://flathub.orf/repo/appstream/com.spotify.Client.flatpakref تثبيت تطبيقات Flatpak باستخدام ملف flatpakref يمكن استخدام ملف flatpakref في حال تحميله إلى الحاسب في تثبيت التطبيق، حيث ننتقل إلى المسار الذي يحوي الملف ومن ثم ننفذ الأمر التالي: flatpak install <ApplicationID>.flatpakref نفترض أن الملف الذي قمنا بتنزيله هو "net.poedit.Poedit.flatpakref" فيصبح الأمر الذي يجب تنفيذه بالشكل التالي: flatpak install net.poedit.Poedit.flatpakref تشغيل تطبيق تم تثبيته عن طريق النظام Flatpak يتم تشغيل التطبيقات التي تم تثبيتها باستخدام نظام Flatpak بتنفيذ الأوامر من الشكل التالي: flatpak run <ApplicationID> فبالعودة للمثال السابق، نشغل التطبيق spotify بتنفيذ الأمر التالي: flatpak run com.spotify.Client عرض جميع التطبيقات المثبّتة باستخدام Flatpak ضمن النظام يمكن عرض التطبيقات التي ثبتها المستخدم ضمن الحاسب بتنفيذ الأمر التالي: flatpak list ليظهر الخرج بالشكل التالي: إزالة تطبيق مثبت باستخدام النظام Flatpak تتم إزالة التطبيقات بتنفيذ أمر من الشكل التالي متضمنًا معرف التطبيق: flatpak uninstall <ApplicationID> ففي حال الرغبة بإزالة تطبيق spotify، ننفذ الأمر التالي: flatpak uninstall com.spotify.Client تحديث جميع التطبيقات المثبّتة باستخدام Flatpak يتم تنفيذ الأمر التالي لإتمام عملية التحديث: flatpak update تحرير المساحة بإزالة التطبيقات غير المستخدمة والمثبّتة باستخدام flatpak يجب تحرير المساحة الخاصة بالتطبيقات غير المستخدمة من فترة لأخرى. يمكن تنفيذ الأمر التالي لتحرير المساحة المرتبطة بتطبيقات ثبتها المستخدم باستخدام نظام Flatpak: flatpak uninstall --unused يستعرض هذا الأمر قائمة التطبيقات غير المستخدمة ويتيح للمستخدم خيار إزالتها. الخاتمة يتيح نظام Flatpak العديد من التطبيقات للمستخدمين حيث أنّ موقع Flathub وسيلة مريحة للعثور على التطبيقات التي يحتاجها المستخدم. يساعد هذا النظام المطورين على إنشاء حزمة واحدة قابلة للعمل على معظم توزيعات لينكس مما يوفر العناء من تطوير حل خاص بكل توزيعة على حدى كما أنّ ذلك يسهل عمليات الصيانة وحل المشاكل أيضًا. يمكن مقارنة هذا النظام بمنافسه Snap، وبمقارنة بسيطة بين هذين النظامين نجد أنّ النظام flatpak أكثر تعقيدًا إذ أنّ اعتماده على معرف التطبيق بدلًا من اسمه يزيد من تعقيده بالنسبة للمستخدم، إلا أنّ تثبيت وإزالة الحزم باستخدام flatpak لا يتطلب صلاحيات متقدمة لسبب ما وهذا الأمر جيد. ترجمة وبتصرف للمقال Using Flatpak on Ubuntu and Other Linux Distributions [Complete Guide]‎ لصاحبه Ambarish Kumar. اقرأ أيضًا كيفية تثبيت التطبيقات في لينكس مدخل إلى مستودعات أوبنتو
  5. توجد العديد من المقالات التي تناقش نظام التشغيل الأفضل بالنسبة للمستخدمين، يعد نظام التشغيل ويندوز Windows الأكثر شيوعًا بين المستخدمين حول العالم. تطور نظام التشغيل لينكس بشكل كبير في السنوات الأخيرة فعلى الرغم من أنه كان نظام التشغيل الأنسب للخوادم بسبب أداءه وموثوقيته العالية إلا أنّه أصبح اليوم مناسبًا لجميع المستخدمين بعد أن امتلك واجهات رسومية مناسبة ودعم العديد من الخدمات التي يحتاجها المستخدمون. تذكر العديد من المقالات أن نظام لينكس أفضل من ويندوز فهو أفضل من ناحية الأمان كما أن المستخدم ليس بحاجة إلى شراء رخصة وتجديدها باستمرار. يجد المستخدم عند رغبته بتثبيت نظام التشغيل لينكس على حاسبه العديد من الإصدارات المختلفة والتي يُطلق عليها اسم التوزيعات فمنها نجد توزيعة أوبونتو Ubuntu وتوزيعة فيدورا Fedora وتوزيعة مينت Mint وغيرها من التوزيعات التي يبلغ عددها المئات. نستنتج من هذا التنوع أمرًا مهمًا حول ماهية لينكس الحقيقية إذ أنّه عبارة عن نواة لنظام التشغيل وليس نظام تشغيل كما يعتقد الكثيرون. نقدم في هذا المقال تشبيهًا ليساعد المستخدم أن يفهم الفارق بين نواة نظام التشغيل والنظام بحد ذاته. على الرغم أن التشبيه مناسب لطرح الفكرة فهو يبقى توضيحًا ومساعدًا لفهم المبدأ وبالطبع لن نجد سؤالًا عن هذا التشبيه في امتحان رسمي أو في مقابلة عمل. لينكس عبارة عن نواة نظام تشغيل فقط تعتبر هذه العبارة واضحة وصحيحة ولكن إذا بحثنا في الكتب أو المقالات التقنية فقد نجد شكلًا يوضح بنية نواة لينكس كما في الشكل التالي: نشبه نظم التشغيل وكأنها مركبات مهما يكن نوعها، تمتلك أية مركبة محرك والذي يمثل أساس هذه المركبة والتي يمكن أيضًا أن نسميها النواة ومن البديهي أنه لا يمكن استخدام المركبة دون هذا الجزء الأساسي. على الرغم من أهميته إلا أنّ المستخدم لا يستطيع أن يقود المحرك مباشرة فهو بحاجة إلى العديد من الأدوات كي تتفاعل مع المحرك ليصل إلى الهدف المرغوب وهو قيادة المركبة، فهو بالحاجة إلى العجلات والمقود وعلبة السرعة والمكابح والكثير من الأدوات التي يتعامل معها مباشرة دون أن يتعامل مع المحرك بشكل مباشر. كذلك الأمر لا يمكن استخدام نواة نظام التشغيل بمفردها وإنما يحتاج المستخدم العديد من الأدوات ومنها الغلاف shell والأوامر والواجهات الرسومية والتي يشير إليها البعض باسم بيئة سطح المكتب وغيرها من الأدوات الأساسية التي يحتاجها المستخدم في أعماله اليومية. التفكير بنظم التشغيل على أنها مركبات نعتبر شركة مايكروسوفت Microsoft بأنها شركة تصنيع سيارات مخصصة لجميع الأغراض والذي يمثل نظام تشغيل ويندوز. تسيطر هذه السيارات على السوق المحلية والعالمية والتي تتضمن محركاتها المحمية ببراءات اختراع والمطورة ضمن الشركة نفسها والتي لا يستطيع أي شخص إنتاجها أو تعديلها دون موافقة الشركة، أي لا تسمح الشركة بتخصيص المحرك مثلًا كما يرغب المستخدم. وبالطبع توجد شركة أبل Apple لتصنيع السيارات أيضًا والتي تقدم السيارات الفخمة باهظة الثمن وفي حال واجهت المستخدم أية مشكلة فيستطيع الاتصال بالدعم الفني والذي يستبدل غالبا السيارة بأخرى. أما بحالة لينكس وتحديدًا محرك لينكس فلا توجد براءة اختراع تحمي هذا المحرك وتقيد المستخدم من تنفيذ التعديلات وعليه يمكن لأي مستخدم تعديل وبناء السيارات بشكل مجاني والتي تمثل أنظمة التشغيل الخاصة بالحواسب المكتبية والدراجات والتي تمثل الأنظمة الصغيرة المضمنة ضمن تجهيزات أخرى مثل الألعاب والتلفاز وغيرها إضافة إلى إنتاج الشاحنات القوية والتي تمثل الخوادم والطائرات النفاثة والتي تمثل الحواسب الفائقة. نلخص ما سبق بالقول: النواة = المحرك نواة لينكس = نوع محدد من أنواع المحركات أنظمة التشغيل للحواسب المكتبية = السيارات أنظمة التشغيل للخوادم = الشاحنات القوية الأنظمة المضمنة = الدراجات بيئة سطح المكتب = جسم السيارة إضافة إلى الأجزاء الداخلية الخاصة بها. السمات themes والأيقونات = طلاء السيارة وجميع المزايا القابلة للتخصيص من قبل المستخدم التطبيقات = الملحقات التي يمكن استخدامها لغرض محدد مثل نظام الموسيقا. لماذا توجد العديد من توزيعات/نظم تشغيل لينكس المتشابهة؟ بالعودة إلى التشبيه السابق فنطرح السؤال لماذا توجد الكثير من أنواع السيارات فتكون الإجابة ببساطة لأنه يوجد عدد كبير من مصنعي السيارات والذين يستخدمون ما أسميناه محرك لينكس وتختلف كل سيارة عن الأخرى بالنوع والغاية منها، وبما أن هذا المحرك متاح للاستخدام والتطوير بشكل مجاني فيستطيع أي شخص بناء مركبة بالاعتماد عليه ولهذا السبب توجد التوزيعات الشهيرة اليوم مثل أوبونتو Ubuntu وديبيان Debian وفيدورا Fedora ومانجارو Manjaro وغيرها من نظم التشغيل أو تسمى بالتوزيعات المعتمدة على نواة لينكس. يستطيع المستخدم أن يلاحظ بسهولة التشابه الكبير بين بعض التوزيعات المبنية على أساس نواة لينكس. يوضح الشكل مقارنة بين نسخة فيدورا بإصدار GNOME ونسخة ديبيان بإصدار GNOME والتي تبين أنهما متشابهان إلى حد كبير. ندعو المكون الذي يعطي لينكس مظهره باسم بيئة سطح المكتب وبالعودة إلى التشبيه الذي اعتمدناه فتمثل هذه البيئة الهيكل الخارجي للسيارة والأجزاء الداخلية الموافقة له. تتيح توزيعات لينكس المختلفة العديد من البيئات وتعرفنا في المثال السابق على إحداها والتي اسمها GNOME وتوجد أيضًا KDE وCinamon وMATE وغيرها. تستخدم الأنواع المختلفة من السيارات لأغراض مختلفة، فالسيارات الصغيرة مناسبة للاستخدام ضمن المدينة بينما تستخدم السيارات ذات الدفع الرباعي ضمن الأماكن الوعرة. يختلف استهلاك الوقود بين الأنواع السابقة وعلى المستخدم أن يختار ما يناسبه وفقًا لأهدافه. كذلك الأمر بالنسبة لبيئات سطح المكتب فالبيئة GNOME تتطلب أن يمتلك الحاسب ذاكرة RAM بحجم أكبر من 4 غيغابايت، بينما تتطلب البيئة Xfce حجم ذاكرة أقل ويبلغ 1 غيغابايت إلا أنه لا يعد الأفضل من حيث المظهر وخصوصًا مقارنة ببيئة GNOME. ارجع إلى مقال KDE Plasma مقابل GNOME: مقارنة بين أشهر بيئات سطح المكتب في لينكس الذي يعرض مقارنة بين أشهر بيئات سطح المكتب في لينكس لمزيد من التفصيل. هل تأتي بيئة سطح المكتب من ضمن التوزيعة أم يجب تثبيتها بشكل منفصل؟ يستطيع المستخدم تثبيت بيئة سطح المكتب التي يفضلها حتى ولو لم تُضمن بشكل مسبق في التوزيعة ونظرًا لأن لينكس مجاني فيستطيع أي مستخدم إجراء أي تعديل يرغب به ولكن بالطبع يجب أن يكون خبيرًا أو أنه قادر على التعلم بسرعة. تجدر الإشارة أن تثبيت بيئة سطح المكتب لن تتشابه في تجربتها مع بيئة أخرى أو بيئة قديمة استخدمتها بشكل كلي فيمكن أن يوجد اختلاف ببعض تطبيقات بيئات سطح المكتب وللأسف يمكن أن تظهر بعض المشاكل أيضًا فعلى سبيل المثال يمكن أن يختفي مؤشر البطارية أو غيرها. بالطبع يمكن أن يبذل المستخدم مجهودًا إضافيًا لحل هذه المشاكل إذا وجدها المستخدم مزعجة ولم يستطع التأقلم معها. تتعامل توزيعات لينكس بشكل مختلف مع التطبيقات تختلف التوزيعات عن بعضها بطريقة تعاملها مع إدارة الحزم البرمجية، تعني إدارة الحزم البرمجية كيفية الحصول على البرامج الجديدة والتحديثات الخاصة بها وبنظام التشغيل. تعود مسؤولية إتاحة التحديثات الأمنية والصيانة على نظام تشغيل/توزيعة لينكس. تتيح بعض نظم تشغيل لينكس البرمجيات الجديدة فور توفرها مباشرة بينما تستغرق بعض التوزيعات وقتًا أطول لاختبار البرمجية. تتيح بعض التوزيعات مثل أوبونتو وسائل مريحة لتثبيت البرمجيات بينما تكون هذه العملية معقدة شوي لبعض التوزيعات مثل غينتوو Gentoo. الخاتمة يعد اختيار توزيعة لينكس مناسبة أمرًا محيّرًا نظرًا للخيارات العديدة المتاحة، وقد تضمن المقال ذكر بعض العوامل الأساسية التي يجب أخذها بعين الاعتبار عند الاختيار. نضيف إلى العوامل سابقة الذكر الدعم الفني، فمما لا شك فيه أن أي مستخدم يرغب بوجود دعم فني قادر على حل المشاكل التي تواجهه وهذا ما ينطبق على لينكس فالتوزيعات مثل أوبونتو تمتلك دعمًا رسميًا مناسبًا إضافة إلى وجود موقع الكتروني يتيح طرح أي استفسار وحل أي مشكلة تواجه المستخدم ترجمة وبتصرف للمقال What is Linux and Why There are 100’s of Linux Distributions? لصاحبه Abhishek Prakash. اقرأ أيضًا عرض موجز لأشهر توزيعات لينكس موازنة بين توزيعة أوبنتو Ubuntu وآرتش Arch من لينكس Linux 10 طرق لتجربة نظام التشغيل لينكس Linux واستكشافه
  6. عندما يتعامل المستخدم مع مخدم بعيد عنه باستخدام جلسة الصدفة Shell فإن هذا الصدفة يجمع الكثير من المعلومات التي تحدد سلوك الخادم وطريقة النفاذ إلى الموارد. تكون بعض هذه الإعدادات محتواة ضمن الإعدادات وبعضها محتوى ضمن مدخلات المستخدم. يستخدم الصدفة مساحة مخصصة ينشئها عندما يتم تأسيس الجلسة مع الخادم حيث تحتوي هذه البيئة متغيرات تحدد خصائص النظام. نستعرض في المقال كيفية التعامل مع البيئة وقراءة وإعداد المتغيرات الخاصة بالبيئة والمتغيرات الخاصة بالصدفة بشكل مباشر وعن طريق ملفات الإعداد الدائمة. كيف تعمل البيئة ومتغيراتها يتم إنشاء عملية Process في كل مرة يتم فيها إنشاء جلسة صدفة جديدة، تعمل هذه العملية على جمع المعلومات التي يجب توفرها لعملية الصدفة والعمليات التي تتولد عنها. يتم الحصول على هذه المعلومات المتعلقة بالإعدادات من مجموعة متنوعة من الملفات وإعدادات النظام. توفر البيئة وسطًا تستطيع عملية الصدفة استخدامه لقراءة أو ضبط الإعدادات وتمرير هذه القيم إلى العمليات الناتجة عنها أيضًا. يتم صياغة البيئة على هيئة سلاسل نصية تمثل أزواجًا من القيم -مفتاح Key-values. ففي حال تمرير عدة قيم فيتم الفصل بينها بواسطة رمز النقطتين (:) حيث يبدو شكل كل زوج كما يلي: KEY=value1:value2:... يتم استخدام علامة التنصيص المزودجة في حال وجود فراغات ضمن القيمة كما في الشكل التالي: KEY="value with spaces" تمثل المفاتيح في هذه الحالة متغيرات والتي يمكن أن يكون لها أحد نوعين وهي إما متغيرات خاصة بالبيئة أو متغيرات خاصة بالصدفة. تعرّف متغيرات البيئة Environment Variables على أنها متغيرات يتم تعريفها من أجل جلسة الصدفة الحالية كما يتم توريثها إلى أية عمليات أو جلسات صدفة مرتبطة بالصدفة الأم. تستخدم متغيرات البيئة لتمرير المعلومات إلى العمليات التي يتم إنشاؤها من الصدفة الذي قام بإنشاء المتغير. أما متغيرات الصدفة Shell Variables فهي متغيرات محتواة بشكل حصري ضمن الصدفة الذي تم تعريفها ضمنه وتستخدم عادة لتعقب بعض المعطيات التجريبية مثل طباعة مسار العمل الحالي. نميز اصطلاحًا بين هذين النوعين أن متغيرات الجلسة تكون مكتوبة بأحرف كبيرة وذلك لتمييزها عن متغيرات البيئة التي تكتب بحروف صغيرة. طباعة متغيرات الصدفة والبيئة ترتبط كل جلسة صدفة بمتغيرات البيئة والصدفة المرتبطة بها. يمكن النفاذ إلى هذه المتغيرات بعدة طرق. نستعرض متغيرات البيئة المتاحة بتنفيذ الأمر env أو printenv وفي حال عدم إجراء أية تعديلات على طريقة العمل فالأمرين السابقين يعملان دون اختلاف. printenv يظهر عندها خرج مشابه لما يلي مع الأخذ بعين الاعتبار أن عدد المتغيرات يختلف من جهاز لآخر: SHELL=/bin/bash TERM=xterm USER=demouser LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca:... MAIL=/var/mail/demouser PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games PWD=/home/demouser LANG=en_US.UTF-8 SHLVL=1 HOME=/home/demouser LOGNAME=demouser LESSOPEN=| /usr/bin/lesspipe %s LESSCLOSE=/usr/bin/lesspipe %s %s _=/usr/bin/printenv لا يوجد اختلاف أي من الأمرين السابقين يتم تنفيذه فيجب أن يبقى الخرج ذاته بالحالتين أما عن الاختلاف بين الأمرين فيظهر عند تخصيص الأمر printenv إذ يمكن أن يطبع المسارات الخاصة بالمتغيرات مثلا بتنفيذ الأمر التالي: printenv PATH فيظهر عندها خرج مشابه لما يلي: /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games بينما يسمح الأمر env بتعديل البيئة التي تستخدمها البرامج عبر تمرير مجموعة من المتغيرات بالشكل التالي: env VAR1="value" command_to_run command_options ترث العمليات الناشئة متغيرات البيئة من العملية الأب مما يسمح بإعادة تحميل بعض القيم أو إضافة متغيرات لبيئة العملية الابن. نستعرض المتغيرات الخاصة بالصدفة باستخدام الأمر set ولكن تجدر الإشارة إلى أنه في حال تنفيذ هذا الأمر بدون أية إضافات فيتم عرض قائمة بجميع متغيرات الصدفة والبيئة وحتى المتغيرات المحلية والتوابع الخاصة بالصدفة ويتم ذلك بتنفيذ الأمر: set يظهر خرج مشابه لما يلي: BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() . . . نظرًا لأن هذه القائمة تكون كبيرة فمن الأفضل تقليل عدد الأسطر البرمجية التي سيتم عرضها ويتم ذلك بتنفيذ الأمر التالي: set | less تبقى كمية المعلومات كبيرة وبعضها ليس مفيدًا مثل بعض التوابع لهذا يمكن تنظيف هذا الخرج بتوجيه الأمر set ليعمل ضمن نمط POSIX بحيث لن تطبع توابع الصدفة ويتم ذلك بتنفيذ الأمر التالي: (set -o posix; set) تظهر قائمة بمتغيرات البيئة والصدفة التي تم تعريفها بشكل مسبق، يمكن تنفيذ مقارنة بين خرج الأمر env و printenv لمحاولة استخلاص متغيرات الصدفة فقط ولكن ذلك لن يكون عمليًا نظرًا لتعدد الطرق التي يعرض فيها كل من الأوامر السابقة نتائجه، تتم عملية المقارنة بتنفيذ الأمر التالي: comm -23 <(set -o posix; set | sort) <(env | sort) يمكن أن يظهر في الخرج بعض متغيرات البيئة نظرًا لأنّ الأمر set يضيف قيم محاطة بإشارات تنصيص بينما لا يستخدم الأمران envو printenv هذه الطريقة مما قد يسبب بعض الاختلافات ولكن يعطي ذلك المستخدم فكرة جيدة عن المتغيرات المستخدمة ضمن البيئة. يعد الاستخدام الأهم لهذه المتغيرات أنها تسمح بإتاحة قيم دائمة تستخدم بين العمليات دون الحاجة إلى كتابتها ضمن ملفات. متغيرات الصدفة والبيئة الشائعة توجد مجموعة كبيرة من متغيرات البيئة والصدفة التي يتم استخدامها بشكل متكرر من قبل المستخدمين، نذكر منها: المتغير SHELL: يصف هذا المتغير الصدفة الذي سيقوم بتفسير الأوامر التي يدخلها المستخدم وتمريرها لنواة نظام التشغيل، يشير المتغير إلى الصدفة bash بشكل افتراضي ولكن يمكن تغيير هذه القيمة إذا اقتضت الحاجة ذلك. المتغير TERM: يحدد هذا المتغير نوع موجه الأوامر الذي سيستخدم عند تنفيذ أمر ما عن طريق الصدفة، تختلف هذه الأنواع تبعًا لمتطلبات التشغيل ولا يتم تغيير قيمة هذا المتغير عادة. المتغير USER: يحدد المستخدم الحالي الذي سجل دخول إلى نظام التشغيل. المتغير PWD: يحدد مسار العمل الحالي. المتغير OLDPWD: يحدد مسار العمل السابق، ويتم استخدام هذا المتغير لإمكانية العودة إلى المسار السابق باستخدام الأمر cd -. *المتغير LS_COLORS:يحدد نمط الألوان المستخدم والذي تتم إضافته -بشكل خياري- إلى خرج الأمر ls بيحث يتم التمييز بين أنواع الملفات عن طريق اللون مما يسهل العمل على المستخدم بشكل كبير. المتغير MAIL: يحدد المسار إلى صندوق البريد الخاص بالمستخدم. المتغير PATH: يتضمن هذا المتغير قائمة المجلدات التي سيفحصها نظام التشغيل بالترتيب للبحث عن الملفات التنفيذية الخاصة بالأوامر التي يدخلها المستخدم. المتغير LANG: يشير هذا المتغير إلى اللغة الحالية والخيارات المحلية إضافة إلى نوع ترميز المحارف المستخدم. المتغير HOME: تشير إلى مسار المجلد الافتراضي الخاص بالمستخدم الحالي. المتغير _: يشير إلى أحدث أمر قد تم تنفيذه. بالإضافة إلى متغيرات الصدفة التالية التي يصادفها معظم المستخدمون في أعمالهم: المتغير BASHOPTS: يتضمن قائمة بالخيارات المستخدمة عندما تنفيذ الأمر الخاص بالصدفة Bash ويفيد ذلك في التأكد من أنّ بيئة الصدفة ستعمل وفق ما هو متوقع أم لا. المتغير BASH_VERSION: يشير إلى رقم الإصدار الخاص بالصدفة Bash بشكل مقروء بالنسبة للمستخدم. المتغير BASHVERSINFO: يشير إلى رقم الإصدار الخاص بالصدفة Bash بشكل خاص بالآلة. المتغير COLUMNS: يشير إلى عدد الأعمدة الذي يمكن استخدامه لعرض خرج الأوامر بما يناسب الشاشة. المتغير DIRSTACK: يتضمن قائمة بالمجلدات المخصصة للمكدسات stacks والتي يتم استخدامها مع أوامر pushd وpopd. المتغير HISTFILESIZE: يشير إلى عدد الأوامر السابقة التي يتم حفظها ضمن الملف الخاص بحفظ الأوامر السابقة. المتغير HOSTNAME: يتضمن اسم المضيف الخاص بالحاسب المستخدم. المتغير IFS: يشير هذا المتغير إلى الفاصل المستخدم بين الكلمات التي يدخلها المستخدم وهي فراغ space بشكل افتراضي. المتغير PS1: يحدد هذا المتغير المؤشر الخاص بموجه الأوامر الرئيسي فنلاحظ بشكل افتراضي أنه يطبع اسم المستخدم الحالي واسم الحاسب بشكل افتراضي إلا أنه يمكن تخصيص هذه الطباعة بتعديل قيمة هذا المتغير، بينما يشير المتغير PS2 إلى تعريف المؤشرات الثانوية عندما يمتد الأمر لأكثر من سطر واحد. المتغير SHELLOPTS: يشير إلى خيارات الصدفة التي يمكن إعدادها باستخدام الأمر set. المتغير UID: يشير إلى رقم التعريف الخاص بالمستخدم UID الخاص بالمستخدم الحالي. إعداد متغيرات البيئة والصدفة تبين الفقرات التالية خطوات إنشاء النوعين السابقين من المتغيرات ويفيد ذلك في التمييز بين هذين النوعين: إنشاء متغيرات الصدفة يمكن تعريف متغير الصدفة للجلسة الحالية بسهولة عبر كتابة اسم المتغير والقيمة التي يتم إسنادها له، يتم ذلك بتنفيذ الأمر التالي: TEST_VAR='Hello World~' نلاحظ استخدام علامة التنصيص بسبب وجود فراغ ضمن قيمة المتغير أما سبب استخدام علامة التنصيص المفردة بدلًا عن المزدوجة كما وضحنا في الفقرة السابقة هو وجود إشارة التعجب والتي تعد محرفًا خاصًا ويستدعي استخدام علامة التنصيص الإفرادية معه أو استخدام محرف الهروب (/) وإلا فإنه سيتم تنفيذ الأمر الخاص بالمحرف المميز وهو في حالة إشارة التعجب استدعاء أمر تم تنفيذه مسبقًا من قائمة الأوامر. أصبح هذا المتغير متاحًا ضمن الجلسة الحالية ولكنه لن يمرر إلى الجلسات التي تنتج عنها، نستعرض هذا المتغير بتنفيذ الأمر: set | grep TEST_VAR يظهر عندها الخرج التالي: TEST_VAR='Hello World!' نتحقق من أنّ هذا المتغير ليس من ضمن متغيرات البيئة بتنفيذ الأمر التالي: printenv | grep TEST_VAR لن تظهر قيمة المتغير في هذه الحالة، نستعرض قيمة المتغير بتنفيذ الأمر echo كما في الشكل: echo $TEST_VAR يظهر عندها الخرج التالي: Hello World! يدرك الصدفة بمجرد وجود رمز $ أن النص التالي يمثل اسم متغير وليس قيمة ثابتة ليقوم بطباعتها كما هي، لنتحقق أنّ هذا المتغير لن يمرر إلى العمليات الناتجة من العملية التي قامت بإنشائه ونبدأ ذلك بإنشاء جلسة صدفة جديدة باستخدام الأمر bash كما يلي" bash echo $TEST_VAR لن تظهر قيمة المتغير في هذه الحالة، نغادر الجلسة الجديدة بتنفيذ الأمر exit الذي يعيدنا إلى جلستنا الأصلية: exit إنشاء متغيرات البيئة نستطيع تحويل متغير الصدفة إلى متغير بيئة عبر تنفيذ ما يعرف بالتصدير export وذلك بتنفيذ الأمر: export TEST_VAR يصبح عندها هذا المتغير خاصًا بالبيئة ونتحقق من ذلك بتنفيذ الأمر التالي: printenv | grep TEST_VAR ليظهر عندها الخرج التالي: TEST_VAR=Hello World! نعيد التجربة السابقة ونتأكد من تمرير المتغير إلى الجلسات الناتجة عن هذه الجلسة بتنفيذ الأوامر التالية: bash echo $TEST_VAR يظهر عندها الخرج التالي: Hello World! أي أنّ العملية الابن استطاعت الحصول على قيمة المتغير. نتأكد أيضًا من قدرتها على إنشاء متغيرات البيئة بتنفيذ الأمر: export NEW_VAR="Testing export" نتحقق من قيمة المتغير بتنفيذ الأمر: printenv | grep NEW_VAR ليظهر الخرج التالي: NEW_VAR=Testing export نعود إلى جلسة الصدفة الأصلية بتنفيذ الأمر التالي: exit ونتحقق من قيمة المتغير الذي تم إنشاؤه بتنفيذ الأمر: echo $NEW_VAR لن يظهر شيء على خرج الشاشة. يعود سبب ذلك إلى أنّ متغيرات البيئة يتم تمريرها من العملية الأب تمرر إلى العملية الابن فقط وليس بالعكس ويعد ذلك مفيدًا في منع البرامج من التأثير على بيئة التشغيل الأساسية التي تحويهم. بعد أن تم الخروج من صدفة الابن تم هدم البيئة وبالتالي إزالة المتغير ولهذا لم تظهر قيمته. إزالة وتخفيض مستوى المتغيرات يمكن للمستخدم إعادة متغير البيئة ليصبح متغير صدفة عبر عملية تعرف باسم تخفيض المستوى demote والتي تُنفّذ بالشكل التالي: export -n TEST_VAR ننفذ الأمر التالي للتحقق بأن هذا المتغير لم يعد خاصًا بالبيئة: printenv | grep TEST_VAR ولكن يجب أن يظهر ضمن قائمة متغيرات الصدفة ونتحقق من ذلك بتنفيذ الأمر: set | grep TEST_VAR ليظهر عندها الخرج التالي: TEST_VAR='Hello World!' نستطيع إزالة المتغير سواء كان متغير بيئة أم متغير صدفة باستخدام الأمر unset بالشكل التالي: unset TEST_VAR ونتأكد من أنّ المتغير لم يعد موجودًا بتنفيذ الأمر التالي: echo $TEST_VAR لن يظهر أي خرج على الشاشة لأن المتغير تمت إزالته. إعداد متغيرات البيئة عند تسجيل الدخول تستخدم العديد من البرامج متغيرات البيئة لتحدد بعض خصائص عملها، وبما أنّ بعض القيم مهمة فلا داعي إلى إعدادها في كل مرة يتم فيها تأسيس جلسة عمل كما أنّ بعض قيم هذه المتغيرات ترتبط بالمستخدم والذي يتم تحديده بعد تسجيل الدخول. الاختلاف بين جلسات الصدفة التفاعلية وغير التفاعلية وذات تسجيل الدخول وبدون تسجيل الدخول يقرأ صدفة bash العديد من ملفات الإعداد المتعلّقة ببدء الجلسة، ومن أهم الاختلافات بين الجلسات أن عملية إنشاء الصدفة تمت بتسجيل دخول login أو بدون تسجيل دخول non-login. تبدأ جلسة الصدفة مع تسجيل الدخول بمصادقة المستخدم user authentication كما يتم عند تسجيل الدخول إلى مخدم باستخدام بروتوكول الاتصال الآمن SSH حيث يتم طلب اسم المستخدم وكلمة المرور أما إذا أنشأ المستخدم جلسة صدفة جديدة باستخدام الأمر bash كما تم في المثال السابق فإنه في هذه الحالة أنشأ جلسة صدفة دون تسجيل دخول حيث لن يُسأل المستخدم عن اسم المستخدم وكلمة المرور. يتم التمييز أيضًا بين الجلسات فيما إذا كانت تفاعلية Interactive أو غير تفاعلية Non-Interactive حيث أنّ الجلسة التفاعلية تتصل بموجه أوامر محدد أما جلسة الصدفة غير التفاعلية فلا تحقق ذلك. إذا تصنف كل جلسة صدفة بأنها تفاعلية أم لا وأنها تمت بتسجيل دخول أم بدونه. تعد جلسة الصدفة التي تبدأ عند استخدام بروتوكول SSH مثالًا على جلسة الصدفة التفاعلية التي تتم بتسجيل دخول بينما يعد تشغيل نص برمجي ما عن طريق موجه الأوامر مثالًا على جلسة صدفة غير تفاعلية بدون تسجيل دخول علمًا أن جلسة موجه الأوامر يمكن أن تكون مزيجًا من الخصائص السابقة. يتم في حالة جلسة الصدفة التي تتطلب تسجيل دخول قراءة الإعدادات والتفاصيل من الملف /etc/profile ومن ثم تبحث عن أول ملف خاص بالصدفة ضمن المجلد الأساسي الخاص بالمستخدم للحصول على أية إعدادات إضافية خاصة بالمستخدم حيث تقرأ الملف الموجود في المسار‎~/.bash_profile أو ضمن المسار ‎~/.bash_login أو ضمن المسار ‎~/.profile وفي حال لم تعثر على ملف فلن تبحث في أية مجلدات أخرى. أما في حالة جلسة الصدفة التي تتم دون تسجيل دخول فتتم قراءة الملف ‎/etc/bash.bashrc ومن ثم قراءة الملف ‎~/.bashrc الخاص بالمستخدم لبناء البيئة. أما الصدفة غير التفاعلي فيقرأ متغير البيئة BASH_ENV الذي يحوي مسار إلى ملف إعدادات والذي يستخدمه من أجل تعريف البيئة الجديدة. صياغة متغيرات البيئة يتيح عدد الملفات الكبير المتعلق بمكان تعريف متغيرات البيئة المرونة في العمل حيث يمكن ضبط بعض الإعدادات لحالات معينة عند تسجيل الدخول مثلًا وعدم إتاحتها في حال عدم تسجيل الدخول ولكن عمليًا تظهر الحاجة إلى تعريف بعض المتغيرات التي تكون مشتركة ضمن جميع أنواع الصدفة المتاحة. يتيح نظام التشغيل لينكس هذا الخيار، فعندما يحتاج المستخدم إلى تعريف متغيرات بيئة خاصة بالمستخدم بحيث تكون متاحة سواء سجل المستخدم الدخول أم لا فيمكن استخدام الملف ‎~/.bashrc والذي يمكن تعديله باستخدام محرر النصوص المتاح كما يلي: nano ~/.bashrc يتضمن هذا الملف عددًا كبيرًا من المتغيرات ومعظمها يكون متعلقًا بإعدادات الصدفة bash والتي ليست متعلقة فعليًا بمتغيرات البيئة. يمكن إعداد المتغيرات كما تم إعدادها بموجه الأوامر بالشكل التالي: export VARNAME=value يمكن إضافة أي متغير بيئة ضمن أي سطر في الملف ‎~/.bashrc بشرط عدم دمجه بمتغير آخر أو كتابته ضمن حلقة تكرار موجودة مسبقًا.نحفظ الملف ونغلقه وعند بدء جلسة صدفة جديدة يتم التصريح عن متغير البيئة الجديد وقراءته وتمريره لبيئة الصدفة أما إذا رغب المستخدم بإجبار الجلسة الحالية على قراءة هذا الملف فيتم ذلك بتنفيذ الأمر التالي: source ~/.bashrc يمكن عند الحاجة لاستخدام متغيرات يمكن استخدامها ضمن نظام التشغيل كاملًا إضافتها إلى الملف ‎/etc/profile أو ‎/etc/bash.bashrc أو ‎/etc/environment. الخاتمة توجد متغيرات الصدفة والبيئة دومًا ضمن جلسات الصدفة حيث تعد هذه المتغيرات ذات فائدة كبيرة بالنسبة للمستخدمين. يعد الاستخدام الأساسي لهذه المتغيرات أن تتحكم العملية الأب بكامل تفاصيل العمليات الأبناء لها سواء تم ذلك عن طريق الملفات أو بدونها. توجد العديد من الحالات التي يعد استخدام متغيرات البيئة ضروريًا فعلى سبيل المثال، تعتمد بعض آليات نشر وتوزيع التطبيقات على متغيرات البيئة لإعداد المصادقة authentication والاحتفاظ ببعض المعلومات الهامة حيث لا يمكن الاحتفاظ بهذه المعلومات ضمن ملفات نظرًا لحساسيتها حيث أنها قد تصبح قابلة للقراءة من قبل جهات غير مخولة بالاطلاع على المحتوى. ترجمة وبتصرف للمقال How To Read and Set Environmental and Shell Variables on Linux لصاحبه Justin Ellingwood. اقرأ أيضًا مدخل إلى كتابة سكربتات الصدفة Shell Scripts؟ ما هو سطر الأوامر؟ أهم 20 أمرا في نظام التشغيل لينكس لجميع المستخدمين
  7. تعرفنا في المقال ما هو محمل الإقلاع GRUB في لينكس وفيما يستخدم على أداة Grub فهي أول قائمة تظهر عند بدء عمل نظام التشغيل لينكس لتعرض الخيارات المتعلّقة بالإقلاع. تتضمن هذه الخيارات أنظمة التشغيل المثبتة على الحاسب إضافة إلى خيارات الوصول إلى إعدادات UEFI وقائمة الاسترداد recovery عند حدوث خطأ ما. يمكن تخصيص العديد من قوائم الأداة Grub، كما يمكن تغيير ترتيب الإقلاع الخاص بأنظمة التشغيل وتغيير المهلة التي يتم بعدها انتقاء الاختيار الافتراضي للإقلاع وإخفاء أنظمة تشغيل محددة وحتى إخفاء شاشة الأداة Grub بالكامل وتغيير صورة الخلفية ضمن الأداة وحتى تبديل الواجهة والألوان والعديد من الخيارات الأخرى. يمكن تخصيص وضبط كل ما سبق بتغيير ملفات إعداد الأداة Grub الموجودة في المسار ‎/etc/default/grub و ‎/boot/grub2 في سطر الأوامر. لكن ذلك ليس سهلًا بالنسبة للعديد من مستخدمي نظام لينكس، لذلك يمكن استخدام أداة ذات واجهة رسومية مثل Grub Customizer وتغيير إعدادات الأداة Grub بسهولة. تثبيت الأداة Grub Customizer ضمن نظام لينكس تتوفر الأداة Grub Customizer في المخازن الرسمية للعديد من توزيعات لينكس الشهيرة. أي أنه يمكن تثبيتها بسهولة من مركز البرامج كما في الشكل التالي: يمكن استخدام مدير الحزم الخاص بالتوزيعة المستخدمة لتثبيت هذه الأداة أيضًا. كما يمكن استخدام الأمر apt لتثبيت الأداة Grub Customizer ضمن أي نظام لينكس معتمد على توزيعة أوبنتو وديبيان: sudo apt install grub-customizer أما في حال تم استخدام توزيعة فيدورا Fedora فيتم استخدام الأمر التالي: sudo dnf install grub-customizer وفي حال توزيعتي آرتش Arch ومانجارو Manjaro فيتم استخدام الأمر التالي: sudo pacman -Sy grub-customizer أما بالنسبة لتوزيعة أوبنتو Ubuntu إصدار 18.04 ومينت Mint إصدار 19، يجب استخدام الأداة PPA. نبدأ بتشغيل موجه الأوامر وتنفيذ ما يلي: sudo add-apt-repository ppa:danielrichter2007/grub-customizer sudo apt update sudo apt install grub-customizer تخصيص الأداة Grub باستخدام أداة الواجهات الرسومية Grub Customizer نبحث عن الأداة Grub Customizer بعد الانتهاء من تثبيتها ونشغّلها. تحتاج الأداة إلى كلمة مرور لمستخدم ذي صلاحيات عالية لأنها تعدّل إعدادات مهمة خاصة بالإقلاع والتي تستدعي وجود صلاحيات مستخدم الجذر root. تظهر الواجهة الرئيسية للأداة بعد إدخال كلمة السر المناسبة. تغيير ترتيب الإقلاع تستخدم الأداة Grub Customizer بشكل أساسي من أجل تغيير ترتيب الإقلاع. ففي حال وجود أكثر من نظام تشغيل على الحاسب كامتلاك نسخة من نظام ويندوز Windows وتوزيعة لينكس بحيث يختار المستخدم النظام الذي يريد العمل معه عند الإقلاع أو حتى في حال وجود أكثر من توزيعة لينكس على نفس الحاسب، فقد يرغب المستخدم في تغيير نظام التشغيل الافتراضي. نختار نظام التشغيل الذي نرغب بجعله افتراضيًا وننقله إلى أعلى القائمة،ننقر على زر الحفظ لتطبيق التعديلات. يبين الشكل التالي تحديد نظام تشغيل ويندوز ليصبح افتراضيًا عند الإقلاع. إصلاح مشكلة إعادة التشغيل المتعددة بعد تحديث نواة نظام التشغيل لا تثبت الأجهزة متعددة الإقلاع التي تستخدم نظام التشغيل ويندوز غالبًا التحديثات بشكل صحيح ما لم تتم إعادة التشغيل مباشرة في هذا النظام. يعني ذلك أنه قد يحتاج المستخدم الإقلاع وإعادة الإقلاع عدة مرات قبل أن يعود كل شيء إلى طبيعته. يمكن أن تظهر هذه المشكلة أيضًا عند استخدام نظام لينكس، عندما يبدأ الجهاز بالإقلاع بواسطة نظام تشغيل خاطئ بعد عملية إعادة التشغيل، لا يتم تثبيت أحدث إصدار من نواة نظام التشغيل لينكس بشكل صحيح في بعض الأحيان. تقدّم الأداة Grub Customizer حلًا لهذا المشكلة. ننتقل إلى النافذة الخاصة بالإعدادات العامة "general settings" ونبحث عن خيار الإدخال الافتراضي "default entry" نبدل الخيار "predefined" إلى "previously booted entry". يتم اختيار آخر نظام تشغيل تم استخدمه دومًا عند الإقلاع بعد إتمام هذا التعديل بغض النظر عن ترتيب الإقلاع المحدد ضمن الأداة Grub. لذلك بعد الانتهاء من تحديث نواة نظام التشغيل، وعند تنفيذ إعادة التشغيل سيتم دائمًا إعادة تشغيل الجهاز إلى نظام التشغيل الصحيح ولن يتلف ملف الإقلاع بسبب هذه المشكلة. تغيير صورة خلفية واجهة الإقلاع Grub تكون عادةً صورة الخلفية لأداة Grub عبارة عن لون أسود أو برتقالي، يستطيع المستخدم تغيير هذه الصورة بواسطة الأداة Grub Customizer. ننتقل إلى التبويب "Appearance Settings" في الشريط الجانبي الأيسر، نجد ضمنه الخيار الخاص بصورة الخلفية "background image". نضغط على هذا الخيار ومن ثم نختار الصورة التي نرغب باستخدامها. نلاحظ أن الأداة تبدأ البحث انطلاقًا من مجلد الجذر، ننقل إلى الدليل الرئيسي ومن ثم إلى مكان وجود الصورة: تحذير: قبل إجراء أي تغييرات أخرى هنا، يجب على المستخدم أن يلتقط صورة للشاشة للون النص إذا تم تغييره، فلا توجد طريقة لمعرفة لون النص الأصلي بعد الآن. هناك أيضًا خيار لتغيير الخط ولكن الأداة Grub Customizer تحذّر من استخدام هذا الخيار لهذا السبب لا يوصي أحد باستخدامه. يمكن أن يضطر المستخدم إلى تغيير النص ولون الخلفية لأنه قد يصبح من الصعب قراءة أسطر قائمة الأداة Grub على صورة الخلفية التي تم تغييرها. يمكن العثور على خيار تغيير النص والخلفية من أجل جميع الخيارات ضمن نفس الشريط الجانبي الذي استخدمناه قبل قليل. نستطيع معاينة التغييرات أثناء تحديد ألوان النص، وبعد أن يختار المستخدم اللون المناسب ننقر فوق زر الحفظ save ونعيد تشغيل الحاسب. يجب أن تظهر الصورة التي تم اختيارها ضمن خلفية قائمة Grub الآن. إزالة صورة خلفية واجهة الإقلاع Grub يستطيع المستخدم في حالة عدم الرضا عن صورة الخلفية التي خصصها مسبقًا أن يستعيد الخلفية القديمة الخاصة بقائمة Grub عن طريق خيار مخفي ضمن قوائم الأداة. ننتقل إلى تبويب إعدادات المظهر "Appearance Settings" ومن ثم ننقر على خيار الإعدادات المتقدّمة "advanced settings" الكائن في الركن الأيمن السفلي. نلغي تحديد الخيار "GRUBMENUPICTURE" ومن ثم نحفظ التغييرات كما في الشكل التالي. تغيير سمة الأداة Grub وإضفاء مظهر جذاب عليها تحذير: تشترط الأداة Grub نوع محدد للصورة وحجم الخط والدقة وما إلى ذلك. يؤدي تغيير سمة الأداة Grub والإعدادات المتعلقة بها كثيرًا إلى الحصول على نظام تشغيل ذي ملفات إقلاع يمكن أن تتلف بسهولة، لهذا يجب أخذ نسخة احتياطية لنظام التشغيل كاملًا أو استخدام أدوات مخصصة لأخذ نسخة احتياطية لإعدادات النظام فقط وتعد الأداة Timeshift مناسبة لذلك، كما يجب أن يحتفظ المستخدم بنسخة من نظام التشغيل بحيث تكون جاهزة للإقلاع مباشرة على قرص USB خارجي لاستخدامها عند الطوارئ. نجد خيار السمة ضمن النافذة "Appearance Settings" في واجهة الأداة Grub Customizer، يمكن تصفح السمات القابلة للاستخدام وتفعيلها من هناك كما في الشكل التالي. يمكن الحصول على سمات خاصة بالأداة Grub من موقع Pling الذي يتضمن قسمًا كاملًا مخصصًا لسمات الأداة Grub: يمكن اتباع النصائح التالية من أجل اختيار سمات Grub مناسبة: التأكد من أنه قد تم تحديث سمة Grub مؤخرًا ونجد هذه المعلومات على صفحة السمة. تقبل الأداة Grub Customizer السمات بتنسيق ‎.tar.gz فقط لذا يجب التحقق أنّ السمة متاحة بهذه اللاحقة أم لا. الانتباه إلى تقييم السمة حيث يشير التقييم السيء لسمة ما أن العديد من المستخدمين واجهوا مشكلة ما بسببه. قراءة الوصف المرفق بالسمة للحصول على معلومات وإرشادات إضافية. قراءة التعليقات الأخيرة المتعلقة بالسمة لمعرفة ما إذا صادف مستخدم ما أخطاء أو مشاكل عند استخدامها. انتبه، يتم إنشاء بعض السمات لتوزيعات محددة، ولن تعمل بعض السمات على بعض التوزيعات حتى لو لم يظهر أي خطأ أو تحذير. عند الانتقال إلى مكان حفظ ملفات سمة الأداة Grub التي تم تنزيلها، نجد محتوياتها ضمن نافذة الأداة Grub Customizer والتي تتيح للمستخدم تعديل إعدادات الأداة Grub وذلك بالطبع إن كان المستخدم متمكنًا من ذلك، مما يتيح له تعديل الملفات وتخصيصها بشكل أكبر ولكن عادة لا يحتاج المستخدم إلى مثل هذا التعديل. يوجد خيار حذف السمة في نفس المكان الذي أضفتها فيه في حال رغبة المستخدم بالتخلص من السمة لسبب ما. هل يجب تخصيص الأداة Grub؟ شخصيًا لا نفضل تخصيص مظهر شاشة Grub ومع ذلك يمكن تغيير المهلة الافتراضية لانتقاء نظام التشغيل من 10 ثوانٍ إلى ثانيتين أو 3 ثوانٍ في حال وجود أكثر من نظام تشغيل مما يسرّع عملية الإقلاع وخصوصًا عندما لا يكون المستخدم قريبًا للضغط على مفتاح لاختيار نظام التشغيل. ترجمة وبتصرف للمقال Customize Grub to Get a Better Experience With Linux لصاحبه Abhishek Prakash. اقرأ أيضًا الدليل النهائي لاختيار توزيعة لينكس تثبيت لينكس مع نظام ويندوز كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة
  8. لا بدّ أنّ أي مستخدم لنظام التشغيل لينكس قد شاهد مثل هذه الشاشة عند بدء عمل حاسبه، فهذه الشاشة هي شاشة GRUB الأساسية في نظام لينكس. نتعرف في هذا المقال على ماهية هذه الأداة واستخداماتها إضافة إلى الحديث عن إعدادها وتخصيصها بما يناسب المستخدم. ما هي الأداة GRUB؟ تعد الأداة GRUB برنامجًا متكاملًا لتحميل وإدارة عملية الإقلاع وتعد هذه الأداة شائعة الاستخدام مع توزيعات لينكس المختلفة. نعرّف برنامج محمل الإقلاع bootloader على أنّه أول برنامج يعمل عند إقلاع الحاسب، إذ يحمّل نواة نظام التشغيل في الذاكرة ومن ثم تهيئ النواة مكونات نظام التشغيل للعمل مثل: الصدفة Shell ومدير الإظهار وبيئة سطح المكتب وغيرها. محمل الإقلاع أم مدير الإقلاع يحصل الكثير من اللغط عند الحديث عن محمل الإقلاع ومدير الإقلاع boot manager، فالأول قد تم تعريفه في الفقرة السابقة أما الثاني فهو برمجية تسمح لك باختيار واحد من أنظمة التشغيل المتاحة ضمن حاسبك عند الإقلاع. يمكن للمستخدم أن يمتلك نسخة من نظام التشغيل Windows ونسخة أخرى من نظام التشغيل لينكس وهنا يأتي دور مدير الإقلاع لإعطاء الخيار للمستخدم حول نظام التشغيل الذي يرغب بإقلاعه. تتضمن جميع توزيعات لينكس انطلاقًا من إصدار النواة رقم 3.3 محمل إقلاع EFI مدمج وفي الحقيقة يجب أن يتضمن أي نظام تشغيل قادر على العمل مع نظام EFI محمل إقلاع مناسب، حيث تتم قراءة جزء نظام EFI والتي يرمز لها بـ ESP اختصارًا إلى EFI System Partition لتحديد موقع ملفات EFI والتي تتضمن معلومات الإقلاع. فالأداة GRUB تنفذ الوظيفتين السابقتين معًا على الرغم مما يوحي اسمها فهذه الأحرف هي اختصار لـ GRand Unified Bootloader. ما الذي تعنيه الأسطر الظاهرة ضمن شاشة GRUB؟ تختلف الأسطر الظاهرة ضمن الشاشة بين توزيعات لينكس وبين طرق الإعداد المختلفة التي يمكن استخدامها، نجد عادة اسم توزيعة لينكس ضمن السطر الأول كما يمكن أن نجد قائمة الخيارات المتقدمة وعند الدخول إليها نلاحظ مجموعة من الأسطر والتي تبدأ بعبارة مشابهة لـ linux-generic-x-y-z. من المزايا المفيدة أنّ نظام لينكس يحتفظ بإصدار واحد أقدم عندما يُحدَّث إصدار نواة نظام التشغيل. لهذا نستطيع اختيار أي نسخة نريد الإقلاع منها. ينقذ هذا الإجراء المستخدمين عندما تظهر مشاكل في النسخة الحديثة حيث يستطيعون متابعة أعمالهم دون انقطاع. يمكن أن نشاهد في نهاية القائمة سطرًا خاصا بإعداد النظام أو إعدادات UEFI وذلك للوصول إلى نظام BIOS الخاص بالحاسوب. برامج أخرى تدير عملية الإقلاع تعد أداة GRUB الأكثر شيوعًا ضمن توزيعات لينكس ولكنها ليست الوحيدة. إذ تعد الأداة rEFInd إحدى الأدوات المعروفة بين مستخدمي أنظمة لينكس. تتميز هذه الأداة بأنها قابلة للتخصيص بشكل كبير كما أنها تمتلك واجهات أجمل من تلك المستخدمة ضمن الأداة GRUB. توجد العديد من الميزات الأخرى منها ما يتعلق بالأمان والأداء ولكن تبقى الأداة GRUB متفوقة بالعديد من النواحي وأهمها أنها متاحة بشكل مباشر ضمن توزيعات لينكس بينما تحتاج الأداة rEDInd إلى دعم من جهة ثالثة Third-Party Support لتعمل بشكل صحيح. يوجد أيضًا مدير إقلاع نصي اسمه systemd-boot المعد خصيصًا لنظام تشغيل لينكس، نجد مدير الإقلاع هذا ضمن بعض توزيعات لينكس مثل Pop OS. التعديل المباشر على عناصر GRUB تتضمن الشاشة الرئيسية للأداة قائمة بنظم التشغيل التي يمكن استخدامها في عملية الإقلاع وذلك في حال وجود أكثر من نظام واحد ضمن الحاسب، يمكن أن يختار المستخدم إصدار محدد من نواة نظام تشغيل لينكس على سبيل المثال من أجل تنفيذ عملية الإقلاع. توجد العديد من الخيارات إضافة إلى تحديد نظام التشغيل الذي نريد الإقلاع منه، فعلى سبيل المثال يمكن أن نختار تعديل بعض المتغيرات الخاصة بنواة نظام التشغيل قبل بدء الإقلاع. من الممكن أن نعطّل التعريفات الخاصة بالإظهار في حال سببت مشكلة ما لنستطيع النفاذ إلى الحاسب وحل هذه المشكلة. يتم تحرير القائمة بالضغط على الحرف "e". كما يمكن الضغط على الحرف "c" للدخول إلى قائمة موجّه الأوامر الخاصة بالأداة GRUB من القائمة السابقة. ملف الإعداد الخاص بالأداة GRUB تكون التعديلات على قوائم الأداة GRUB مؤقتة فإذا أردنا أن تصبح دائمة فيجب تعديل ملف الإعداد الخاص بالأداة وذلك بعد إقلاع نظام التشغيل. نجد في نظام لينكس ملف الإعداد الخاص بالأداة GRUB ضمن المسار ‎/etc/default/grub وتجدر الإشارة إلى وجود مجلد أيضًا خاص بالأداة ضمن المسار ‎/etc/default/grub.d. يمكن التعديل على الملف مباشرة إلا أن ما ينصح به المختصون أن ننشئ ملفات إعداد إضافية ضمن المجلد والتي يكون لها اللاحقة ‎.cfg وتعديلها. يجب بعد إتمام التعديلات أن نطلب من محمل الإقلاع أن يقرأ الملف الجديد، لكن هذا يحدث تلقائيًا بعد عملية تثبيت نظام تشغيل لينكس جديد إلى جانب نظام موجود حيث سيحدث محتوى الملف بشكل تلقائي بمعلومات النظام الجديد. أداة تخصيص الأداة GRUB يتخوف الكثير من المستخدمين وتحديدًا غير المختصين منهم من استخدام الأدوات النصية في تعديل الملفات الحساسة مثل تلك الخاصة بالإقلاع. تحل هذه المشكلة باستخدام الأداة الرسومية GRUB Customizer والتي تتيح تغيير ترتيب الإقلاع والعديد من المتغيرات المهمة وحتى يمكنها تغيير صورة الخلفية الخاصة بالأداة GRUB إذا رغب المستخدم بذلك. الخاتمة تضمن هذا المقال تعريفًا عامًا للأداة GRUB وعملية تحميل الإقلاع وإدارته، في الحقيقة تحتوي هذه الأداة العديد من الخيارات المعقدة والتي نتركها إلى مقالة تفصيلية أخرى. يمكن عند الرغبة باكتساب معلومات تفصيلية عن هذه الأداة مراجعة التوثيق الرسمي لها ضمن موجه الأوامر الخاص بنظام لينكس عبر تنفيذ الأمر info grub ليظهر خرج مشابه للشكل التالي ترجمة وبتصرف للمقال ?Linux Jargon Buster: What is Grub in Linux? What is it Used for لصاحبه Abhishek Prakash. اقرأ أيضًا تخصيص محمل الإقلاع Grub للحصول على تجربة أفضل مع نظام لينكس ما هو نظام التشغيل لينكس؟ كيفية تثبيت توزيعة آرتش Arch من لينكس
  9. تُبسّط أداة دوكر Docker إدارة إجراءات التطبيق في الحاويات؛ إذ تشبه الحاويات الأجهزة الافتراضية Virtual Machines بالكثير من الجوانب، إلا أنها تتميز بخفة الوزن كما أنها أفضل من ناحية استخدام الموارد. يتيح ذلك للمطورين تجزئة بيئة التطبيق إلى خدمات معزولة متعددة. يصبح تنظيم جميع الحاويات التي تعود للخدمات المختلفة التي يعتمد تطبيق ما عليها أمرًا صعبًا، إذ أنّ تشغيلها معًا والاتصال فيما بينها وحتى إيقافها عن العمل يدويًا ليس عمليًا. تسمح أداة دوكر كومبوز Docker Compose بتشغيل بيئات التطبيق متعددة الحاويات اعتمادًا على مجموعة تعريفات مُخزّنة في ملف YAML، كما تبني هذه الأداة بيئات كاملة قابلة للتخصيص حسب الحاجة متضمنة العديد من الحاويات التي تتشارك الشبكات وأقراص التخزين فيما بينها. نوضح فيما يلي طريقة تثبيت الأداة دوكر كومبوز على خادم ذي نظام تشغيل لينكس أوبونتو Ubuntu إصدار 20.04 وكيفية استخدام هذه الأداة. المتطلبات الأساسية يجب توفير ما يلي: الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو (استعملنا الإصدار 20.04 في هذا المقال) أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo، ولا يُفضّل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم، كما يُفضل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت أداة دوكر على الخادم أو الجهاز المحلي. ملاحظة: نعمل على تثبيت Docker Compose v1، والذي يستخدم "docker-compose"، ولكن بدءًا من Docker Compose v2، انتقل Docker نحو استخدام أمر الإضافة "compose" كما هو موثّق في أحدث إصدار Ubuntu 22.04، بعيدًا عن "docker-compose" الأصلي. وعلى الرغم من اختلاف طريقة التثبيت إلا أن الاستخدام الفعلي قد لا يتعدى لدى كثيرٍ من المستخدمين التخلص من الرمز "-" بين الكلمتين ليتحول الاستدعاء "docker-compose" إلى "docker compose". نجد ضمن وثائق Docker الرسمية مزيدًا من المعلومات حول توافق الأوامر بين "compose" الجديد و "Docker-compose" القديم. الخطوة 1 - تثبيت الأداة دوكر كومبوز نرغب بتثبيت أحدث إصدار مستقر من الأداة دوكر كومبوز، لذلك سنستخدم المستودع الرسمي GitHub من أجل ذلك. نبدأ بالتحقق من توفر أحدث إصدار ضمن صفحة الإصدارات الخاصة بهم. تجدر الإشارة إلى أن أحدث إصدار مستقر في وقت كتابة هذا المقال هو "1.29.2". نبدأ تحميل الإصدار "1.29.2" وحفظ الملف القابل للتنفيذ في "/usr/local/bin/docker-compose/"، مما سيجعل هذا البرنامج متاحًا للاستخدام عند الحاجة باستدعاء الأمر docker-compose. ننفذ الأمر التالي لتحقيق ذلك: $ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose نعرّف الأذونات الصحيحة ليصبح الأمر docker-compose قابلاً للتنفيذ كما يلي: $ sudo chmod +x /usr/local/bin/docker-compose نتحقق من نجاح عملية التثبيت، بتنفيذ الأمر التالي: $ docker-compose --version يظهر على الشاشة خرجٌ مشابهٌ لما يلي: docker-compose version 1.29.2, build 5becea4c انتهت عند هذه المرحلة عملية تثبيت الأداة دوكر كومبوز بنجاح. نبدأ الآن بإعداد ملف "docker-compose.yml" للحصول على بيئة محتواة وتشغيلها باستخدام هذه الأداة. الخطوة 2 - إعداد ملف docker-compose.yml نستطيع إنشاء أية بيئة نرغب بها عبر إعداد ملف "docker-compose.yml" ولتوضيح كيفية إعداد هذا الملف والعمل مع دوكر كومبوز، سننشئ بيئة خادم ويب باستخدام صورة Nginx الرسمية من Docker-Hub ، الذي يعرّف بأنه سجل دوكر العام. ستخدّم هذه البيئة المحتواة ملف HTML واحد ساكن static، أي لا يتضمن محتويات متغيرة. أنشئ مجلّدًا جديدًا في مجلدك الافتراضي، ثم انتقل إليه: $ mkdir ~/compose-demo $ cd ~/compose-demo ثم اضبط مجلد التطبيق ليكون المجلد الجذر لبيئة خادم Nginx على النحو التالي: $ mkdir app أنشئ الملف "index.html" باستخدام محرر النصوص المفضل عن طريق إنشاء ملف جديد داخل مجلد "app" على النحو التالي: $ nano app/index.html نضيف المحتوى التالي إلى هذا الملف: <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Docker Compose Demo</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css"> </head> <body> <h1>This is a Docker Compose Demo Page.</h1> <p>This content is being served by an Nginx container.</p> </body> </html> نحفظ ونغلق الملف عند الانتهاء ويكون ذلك عند استخدام محرر النصوص نانو nano، بالضغط على الاختصار "CTRL + X"، ثم الزر "Y" ثم زر الإدخال "ENTER" للتأكيد. أنشئ بعد ذلك الملف "docker-compose.yml" بتنفيذ الأمر التالي: $ nano docker-compose.yml أضف المحتوى التالي إلى ملف "docker-compose.yml": version: '3.7' services: web: image: nginx:alpine ports: - "8000:80" volumes: - ./app:/usr/share/nginx/html يبدأ ملف "docker-compose.yml" عادةً بتحديد رقم الإصدار "version". إذ يُعلم هذا الرقم الأداة دوكر كومبوز أي إصدار من الإعدادات سيُستخدم. نجد بعد رقم الإصدار جزء الخدمات "services"، إذ تُعد هنا الخدمات التي تشكّل هذه البيئة. يتضمن تطبيقنا الحالي خدمةً واحدةً فقط نسميها "web"، وتستخدم هذه الخدمة صورة "nginx: alpine" وتضبط إعادة توجيه المنفذ باستخدام الموجّه "ports"، ويعني ذلك إعادة توجيه جميع الطلبات الواردة إلى المنفذ "8000" من الجهاز المضيف (النظام الذي يُشغِّل أداة دوكر كومبوز) إلى حاوية "web" عبر المنفذ "80" حيث يعمل خادم Nginx. ينشئ الموجّه "volumes" وحدة تخزين مشتركة بين الجهاز المضيف والحاوية. نختار مشاركة المجلد "app" الموجود محليًا مع الحاوية، إذ أنّ مسار تخزين المجلد داخل الحاوية هو "usr/share/nginx/html/" والذي يصبح الصفحة الافتراضية لخادم Nginx. احفظ الملف واغلقه. انتهى إعداد صفحة توضيحية وملف "docker-compose.yml" لإنشاء بيئة خادم ويب محتواة. نحتاج لاختبار هذه البيئة وتشغيلها باستخدام أداة دوكر كومبوز. الخطوة 3 - تشغيل أداة دوكر كومبوز نستدعي أداة دوكر كومبوز بعد الانتهاء من إعداد الملف "docker-compose.yml"، وعندها يمكن إرسال الطلب إلى الخادم. يبدأ الأمر بتحميل صور دوكر الضرورية وإنشاء حاوية لخدمة "web"، وفي النهاية تشغيل البيئة الحاوية بالنمط المخفي، وذلك بتنفيذ الأمر التالي: $ docker-compose up –d تبحث أداة دوكر كومبوز أولاً عن النسخة المحددة ضمن حاسبك المحلي، وإذا لم يعثر عليها، يُحمّل الصورة من مخزن Docker Hub ويحتفظ بها في حال الحاجة لها لاحقًا، يظهر الخرج على نحوٍ مشابهٍ لما يلي: Creating network "compose-demo_default" with the default driver Pulling web (nginx:alpine)... alpine: Pulling from library/nginx cbdbe7a5bc2a: Pull complete 10c113fb0c77: Pull complete 9ba64393807b: Pull complete c829a9c40ab2: Pull complete 61d685417b2f: Pull complete Digest: sha256:57254039c6313fe8c53f1acbf15657ec9616a813397b74b063e32443427c5502 Status: Downloaded newer image for nginx:alpine Creating compose-demo_web_1 ... done ملاحظة: في حال طباعة ما يدل على أنه توجد مشكلة في الأذونات، فهذا يعني أنّ أداة دوكر غير قادرة على العمل دون صلاحية sudo ويجب حل هذه المشكلة أولًا قبل متابعة العمل. أصبحت البيئة جاهزة وتعمل في الخلفية، نتحقق من أن الحاوية نشطة عبر تنفيذ الأمر: $ docker-compose ps تظهر معلومات حول الحاويات قيد التشغيل وحالتها، إضافةً إلى عمليات إعادة توجيه المنافذ المستخدمة حاليًا: Name Command State Ports ---------------------------------------------------------------------------------- compose-demo_web_1 /docker-entrypoint.sh ngin ... Up 0.0.0.0:8000->80/tcp نستطيع الوصول إلى التطبيق التوضيحي من خلال طلب الرابط "localhost:8000" ضمن متصفح الويب في حال كان تشغيل العرض التوضيحي على الجهاز المحلي، أو "yourserverdomainorIP: 8000" في حال كان تشغيل العرض التوضيحي على خادم بعيد. يظهر ضمن المتصفح محتوى كما يلي: تحافظ وحدة التخزين المشتركة التي اعددناها داخل ملف "docker-compose.yml" على مزامنة ملفات مجلد "app" الموجود محليًا مع المجلّد الموجود ضمن الحاوية، أي أنّ أية تغييرات على ملف "index.html" ستنعكس تلقائيًا على المتصفح عند إعادة تحميل الصفحة. الخطوة 4 - التعرف على أوامر الأداة دوكر كومبوز تستخدم أوامر الأداة دوكر كومبوز لإدارة البيئة المحتوية والتفاعل معها. نتحقق من السجلات المُتشأة عن عمل حاوية خادم Nginx، باستخدام الأمر logs: $ docker-compose logs يظهر محتوًى مشابه لما يلي: Attaching to compose-demo_web_1 web_1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration web_1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ web_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh web_1 | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf web_1 | 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf web_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh web_1 | /docker-entrypoint.sh: Configuration complete; ready for start up web_1 | 172.22.0.1 - - [02/Jun/2020:10:47:13 +0000] "GET / HTTP/1.1" 200 353 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "-" نستطيع إيقاف تنفيذ البيئة مؤقتًا دون تغيير الحالة الراهنة للحاويات بتنفيذ الأمر: $ docker-compose pause ليكون الخرج على النحو التالي: Pausing compose-demo_web_1 ... done نستأنف تنفيذ البيئة بتنفيذ الأمر التالي: $ docker-compose unpause ويكون الخرج على النحو التالي: Unpausing compose-demo_web_1 ... done ينهي الأمر stop تنفيذ الحاوية، لكنه لن يزيل البيانات المرتبطة بالحاويات: $ docker-compose stop ويكون الخرج على النحو التالي: Stopping compose-demo_web_1 ... done نستخدم الأمر down من أجل إزالة الحاويات والشبكات ووحدات التخزين المرتبطة بالبيئة الحاوية بتنفيذ الأمر التالي: $ docker-compose down يظهر الخرج على النحو التالي: Removing compose-demo_web_1 ... done Removing network compose-demo_default لن يزيل تنفيذ هذا الأمر الصورة الأساسية التي تستخدمها أداة دوكر كومبوز لإنشاء البيئة وهي "nginx:alpine"، وعند تطبيق الأمر docker-compose up فتُنجز العملية بسرعة لأن هذه الصورة موجودة على الجهاز المحلي ولا داعي لتحميلها من الموقع الرسمي مجددًا. نزيل الصورة الأساسية عند الحاجة إلى ذلك بتنفيذ الأمر التالي: $ docker image rm nginx:alpine وتكون المخرجات على النحو التالي: Untagged: nginx:alpine Untagged: nginx@sha256:b89a6ccbda39576ad23fd079978c967cecc6b170db6e7ff8a769bf2259a71912 Deleted: sha256:7d0cdcc60a96a5124763fddf5d534d058ad7d0d8d4c3b8be2aefedf4267d0270 Deleted: sha256:05a0eaca15d731e0029a7604ef54f0dda3b736d4e987e6ac87b91ac7aac03ab1 Deleted: sha256:c6bbc4bdac396583641cb44cd35126b2c195be8fe1ac5e6c577c14752bbe9157 Deleted: sha256:35789b1e1a362b0da8392ca7d5759ef08b9a6b7141cc1521570f984dc7905eb6 Deleted: sha256:a3efaa65ec344c882fe5d543a392a54c4ceacd1efd91662d06964211b1be4c08 Deleted: sha256:3e207b409db364b595ba862cdc12be96dcdad8e36c59a03b7b3b61c946a5741a الخاتمة تضمن هذا المقال خطوات تثبيت الأداة دوكر كومبوز وإعداد بيئة حاوية بالاعتماد على صورة خادم الويب Nginx، كما تضمن بعض الأوامر الأساسية لإدارة هذه البيئة. ترجمة -وبتصرف- للمقال How To Install and Use Docker Compose on Ubuntu 20.04 لصاحبيه Tony Tran و Erika Heidi. اقرأ أيضًا إعداد حاوية لتطبيق لارافيل باستخدام دوكر كومبوز Docker Compose تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose كيفية تثبيت Docker Compose على دبيان نقل سير عمل Docker Compose إلى Kubernetes إعداد لارافيل مع خادم Nginx وقاعدة بيانات MySQL باستخدام دوكر كومبوز Docker Compose
  10. يُعد Helm مدير حزم ضمن كوبيرنتس Kubernetes، وهو يسمح للمطورين و المشغلين إعداد وتطوير التطبيقات ضمن عناقيد Kubernetes. يُطلق على حزم Helm اسم المخططات Charts، وهي تتضمن قوالبًا لتعريف الموارد التي تضبط وتركب التطبيقات بأقل جهد ممكن. يستطيع المستخدم باستخدام القولبة templating إدارة المخططات وضبطها والتحكم بسلوكها بتمرير تعريفات متنوعة دون تعديل المخططات الأساسية. ويدير Helm تعريفات الموارد المخصصة إضافةً الى التعديلات على التعريفات المستخدمة مسبقًا. تسمى المخططات المنفذة مع المُخصصة من قبل المستخدم باسم الإصدار Release. سنعمل في هذا المقال على إعداد Helm وتوضيح كيفية تثبيت وترقية والتراجع عن الترقية، إضافةً إلى إدارة المخططات والإصدارات، كما سننشئ المخططات الخاصة بنا مع إعداد مخازن المخططات التي تحتضن هذه المخططات. المتطلبات الأساسية عنقود Kubernetes يدعم التحكم بالوصول على أساس الدور role-based access control -أو اختصارًا RBAC- كما هو متاح في المخزن الرسمي. أداة موجه الأوامر"kubectl" ضمن الحاسب المحلي قادرة على الاتصال بالعنقود، والتي تُعد وفقًا للتوثيق الرسمي. نتحقق من الاتصال بالعنقود بتنفيذ الأمر التالي: $ kubectl cluster-info يكون الاتصال بالعنقود ناجحًا ما لم تظهر أخطاء نتيجةً للأمر السابق، أما في حالة وجود عدة عناقيد، نحدد سياق context العنقود المطلوب عبر تنفيذ الأمر التالي: $ kubectl config get-contexts يظهر الخرج لائحةً بالإعدادات المتوفر ة كما يلي: CURRENT NAME CLUSTER AUTHINFO NAMESPACE * do-fra1-helm3-example do-fra1-helm3-example do-fra1-helm3-example-admin تشير النجمة * إلى أن الاتصال الحالي خاص بالعنقود do-fra1-helm3-example؛ وللتبديل إلى عنقود آخر ننفذ الأمر التالي: $ kubectl config use-context context-name ننتقل إلى الخطوة التالية بعد التأكد من اختيار العنقود الذي نرغب باستخدامه لتثبيت مدير الحزم Helm عليه. الخطوة 1- تثبيت مدير الحزم Helm 3 نعتمد طريقة تثبيت مدير الحزم Helm 3 باستخدام السكربت script المُتاح على الموقع الرسمي. نبدأ بالتنقل إلى المجلد "tmp/"حيث نخزّن البرنامج النصي الخاص بالتثبيت. نحقق التنقل بتنفيذ الأمر: $ cd /tmp نحمّل السكربت بتنفيذ الأمر التالي: $ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 يُعد التحقق من محتوى السكربت قبل تثبيته من الممارسات الجيدة المتعلّقة بالأمان، ونستخدم محرر النصوص المفضل من أجل ذلك، إذ نستعرض محتوى الملف "get_helm.sh" قبل تثبيته. نضيف قابلية التنفيذ إلى السكربت بعد التأكد من سلامته بتنفيذ الأمر التالي: $ chmod u+x get_helm.sh ننفذ السكربت لتبدأ عندها عملية تثبيت مدير الحزم Helm 3 عبر تنفيذ الأمر: $ ./get_helm.sh يظهر خرجٌ مشابهٌ لما يلي: Downloading https://get.helm.sh/helm-v3.5.2-linux-amd64.tar.gz Verifying checksum... Done. Preparing to install helm into /usr/local/bin helm installed into /usr/local/bin/helm وبهذا ينتهي تثبيت مدير الحزم Helm 3 على الجهاز المحلي. الخطوة 2- إعداد مخازن المخططات تُخزّن مخططات مدير الحزم Helm ضمن مخازن مخططات قابلة للاستضافة من أي مستخدم وضمن أي جهاز. لا يترافق مدير الحزم Helm 3 عادةً مع أي مخزن مُعد مسبقًا. وعلى الرغم من أن النسخ السابقة من مدير الحزم Helm تضمنت مخزن مخططات مركزي منسق، إلا أنّ تصميم مدير الحزم Helm 3 يحُث المطورين على إدارة مخازنهم الخاصة، إذ يسمح ذلك بحرية أكبر وكذلك الحصول على إصدارات بصورةٍ أسرع، ومعنى ذلك أننا نحتاج إضافة مخزن مستضيف لكل مخطط نستخدمه ضمن مدير الحزم Helm. نستخدم الموقع ArtifactHub.io لإيجاد المخزن المناسب، وهو موقع مفتوح المصدر مُدار من قبل CNCF التي تدير مخططات مدير الحزم Helm ومخازنها، كما تتعقب أكثر المخططات شعبيةً وفائدةً والتي تستخدمها مشاريع CNCF الأخرى. ولذلك تختلف عن المخازن المستقرة "stable" التي استخدمتها الإصدارات السابقة من مدير الحزم Helm. يتضمن الموقع كثيرًا من المخططات المهمة للمشاريع الشائعة، مثل مشاريع Nginx، ومشاريع أدوات المراقبة. نبحث عن المخططات الواجب تثبيتها عبر الصفحة الرئيسية، إذ نبدأ بالبحث عن "nginx" مثلًا لتظهر المخططات المتعلّقة به. نثبت النسخة المجانية Community edition المدارة من قبل فريق Kubernetes، كما نبحث عن "ingress-nginx" ونختاره من بين النتائج كما في الشكل التالي: يمتلك المخطط توصيفًا يبين المهام التي ينفذها مع الأوامر اللازمة لإضافة مخازنه الى الحاسب وتثبيت المخطط، ويمكن الحصول على الأوامر الضرورية عبر النقر على زر INSTALL في يمين الصفحة. ننقر على الزر الازرق الموجود إلى جانب الأمر لنسخه، ونبدأ بنسخ وتنفيذ الأمر الأول: $ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx ننفذ الأمر helm repo add لاضافة المخزن إلى مدير الحزم Helm، إذ يتطلب هذا الأمر تمرير متغيرين، هما: اسم المخزن ورابطه، ويظهر خرجٌ مشابهٌ لما يلي: "ingress-nginx" has been added to your repositories ننفذ الأمر التالي لإعلام مدير الحزم Helm بوجود مخزن جديد يجب عليه التعرّف على محتواه: $ helm repo update يظهر الخرج التالي ليشير إلى نجاح التحديث: Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "ingress-nginx" chart repository Update Complete. ⎈Happy Helming!⎈ تعرفنا في هذه الخطوة على موقع ArtifactHub وما يقدمه، كما أضفنا أيضًا مخزنًا جديدًا إلى تثبيت مدير حزم Helm. وسنثبّت في الخطوة التالية مخطط Helm. الخطوة 3- تثبيت مخطط Helm يملك كل مخطط متغيرات خاصة بالإعداد تحدد سلوكه، إذ تُخزَّن هذه المتغيرات ضمن الملف "values.yaml" الموجود ضمن المخطط، ونستطيع التعرّف على هذه المتغيرات بتنفيذ الأمر التالي مع ضرورة استبدال chart_name باسم المخطط الذي نريد معرفة متغيراته كما يلي: $ helm show values chart_name نتعرّف على المتغيرات الخاصة بمخطط "ingress-nginx" بتنفيذ الأمر التالي: $ helm show values ingress-nginx/ingress-nginx يظهر خرج طويل جدًا يمثل محتويات "values.yaml" الخاص بمخطط "ingress-nginx". نثبت المخطط باستخدام الأمرhelm install على النحو التالي: $ helm install release_name repository/chart_name عرّفنا الإصدار بأنه عينة من المخطط والتي ندعوها بالأمر السابق باسم "ingress-nginx". يثبّت الأمر السابق المخطط ضمن العنقود اعتمادًا على القيم الافتراضية للمتغيرات والتي تُعدّل عند الحاجة باستخدام set-- يتلوها اسم المتغير والقيمة الجديدة كما يلي: $ helm install ingress-nginx/ingress-nginx --set variable_name=variable_value يمكننا تكرار الإضافة set-- لجميع المتغيرات التي تحتاج للتعديل، وطالما أننا لن نخصّص المخطط الآن سنستخدم القيم الافتراضية في عملية التثبيت ونتابع بتنفيذ الأمر التالي: $ helm install ingress-nginx ingress-nginx/ingress-nginx يظهر الخرج التالي بعد نجاح العملية: NAME: ingress-nginx LAST DEPLOYED: Wed Feb 24 10:12:37 2021 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: The ingress-nginx controller has been installed. It may take a few minutes for the LoadBalancer IP to be available. You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-nginx-controller' … يجب الانتباه إلى أن المتغير NAME يقابل اسم الإصدار الذي حددناه سابقًا. يُدرج مدير الحزم Helm المعلومات العامة، مثل حالة الإصدار ونطاق الاسم namespace التي نُشرت ضمنه. يختلف قسم الملاحظات NOTES بين المخططات وغالبًا ما يحتوي دليلًا مختصرًا أو تحذيرات من بعض المشاكل الشائعة عند استخدام موارد المخطط. يتضمن جزء الملاحظات تحذيرًا بأن إعداد موازن الحمل Load Balancer قيد الإنشاء وأن هذه العملية تستغرق وقتًا كي تنتهي. نتحقق من المخططات باستخدام الأمر التالي: $ helm list نجد أن المخطط "ingress-nginx" هو المخطط الوحيد المُتاح في الوقت الحالي: NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION ingress-nginx default 1 2021-02-24 10:12:37.281049711 +0000 UTC deployed ingress-nginx-3.23.0 0.44.0 ونجد الخدمات الخاصة بهذا المخطط ضمن العنقود عن طريق تنفيذ الأمر التالي: $ kubectl get services ليظهر خرجٌ مُشابهٌ لما يلي: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller LoadBalancer 10.245.211.81 46.101.68.67 80:30704/TCP,443:30700/TCP 7m19s ingress-nginx-controller-admission ClusterIP 10.245.50.17 <none> 443/TCP 7m19s kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 83m الآن، بعد أن نشرنا إصدارًا في العنقود، سنعدل ضبطه أثناء عملية النشر. الخطوة 4 - ترقية الإصدار لا نحتاج إلى إزالة الإصدار كليًا عند الحاجة إلى إجراء تعديلات في ضبطه، إذ نستخدم الأمرhelm upgrade لترقية الإصدار بنسخة جديدة من المخطط أو تطبيق الإعدادات الجديدة. يعرض المخطط "ingress-nginx" متغيرًا اسمه controller.replicaCount يتحكم بعدد حجيرات التحكم controller pods المنشورة، ويمكن التأكد من عددها باستخدام الأمر التالي وعادةً ما تكون القيمة الافتراضية لهذا المتغير تساوي الواحد: $ kubectl get pods يظهر الخرج بوجود حجيرة واحدة فقط على النحو التالي: NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7fc74cf778-kjtst 1/1 Running 0 12m نستطيع إضافة مزيدٍ من الحجيرات من أجل التكرارية Redundancy (ثلاثة على سبيل المثال) عبر ترقية الإصدار وتعديل قيمة المتغير الى 4 من خلال الأمر التالي: $ helm upgrade ingress-nginx ingress-nginx/ingress-nginx --set controller.replicaCount=3 --reuse-values يمكن استخدام values -reuse--، الذي يوجّه مدير الحزم Helm ببناء التعديلات على أساس الإصدار المنشور مع الحفاظ على الإصدار السابق. نلاحظ في الخرج أنّ مدير الحزم Helm يزيد من رقم الاشعار لهذه المراجعة للإشارة إلى ترقية الإصدار: NAME: ingress-nginx LAST DEPLOYED: Wed Feb 24 12:07:54 2021 NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None NOTES: … يمكن الحصول على قائمة بالحجيرات المتاحة بتنفيذ الأمر التالي: $ kubectl get pods نلاحظ وجود ثلاث حجيرات عوضًا عن حجيرة واحدة: NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7fc74cf778-4hk9g 1/1 Running 0 18s ingress-nginx-controller-7fc74cf778-kjtst 1/1 Running 0 22m ingress-nginx-controller-7fc74cf778-wz595 1/1 Running 0 18s سنتراجع في الخطوة التالية عن التغييرات ونحذف الإصدارات تمامًا. الخطوة 5 - التراجع و حذف الإصدار يخزّن مدير الحزم Helm رقم المراجعة لكل إصدار داخليًا، بحيث يزداد هذا الرقم عند ترقية الإصدار، ويسمح ذلك بالعودة الى المراجعة السابقة عند الحاجة. نستطيع إعادة عدد الحجيرات إلى واحد وهي القيمة الافتراضية التي عدلناها في الخطوة السابقة، ننفذ الأمر helm upgrade مرةً أخرى ونحدد العدد يدويًا لأنه تغيير بسيط. تصبح هذه العلمية في حالة المخططات الكبيرة التي تمتلك عددًا كبيرًا من المتغيرات دون جدوى ويجب أتمتة عملية تعديل هذه المتغيرات. نتراجع عن الإصدار بتنفيذ الأمر helm rollback: $ helm rollback release_name release_revision ويمكننا التراجع مثلًا عن التعديلات السابقة الخاصة بالمخطط "ingress-nginx" بالعودة الى المراجعة رقم 1 من خلال تنفيذ الأمر التالي: $ helm rollback ingress-nginx 1 يظهر الخرج التالي الذي يشير إلى نجاح العملية: Rollback was a success! Happy Helming! نتحقق من رقم المراجعة الحالية عن طريق طلب قائمة الإصدارات بتنفيذ الأمر التالي: $ helm list نجد أن المراجعة أصبحت 3 بدلًا من 1: NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION ingress-nginx default 3 2021-02-24 12:43:21.523664768 +0000 UTC deployed ingress-nginx-3.23.0 0.44.0 ينظر مدير الحزم Helm لأي تغيير ومن ضمنها التراجع على أنه مراجعة جديدة للإصدار. نتحقق من أن المراجعة رقم 3 مماثلةٌ للأولى عن طريق التحقق من عدد الحجيرات المنشورة بتنفيذ الأمر التالي: $ kubectl get pods نلاحظ وجود حجيرةٍ واحدةٍ فقط في الخرج: NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7fc74cf778-kjtst 1/1 Running 0 41m نستطيع حذف إصدار ما وكل المراجعات المتعلقة به بتنفيذ الأمر helm delete: $ helm delete release_name لم نعد بحاجة لمخطط "ingress-nginx"، لذالك نحذفه بتنفيذ الأمر التالي: $ helm delete ingress-nginx يظهر خرجٌ مشابهٌ لما يلي: release "ingress-nginx" uninstalled نتحقق من قائمة الإصدارات والتي يجب أن تكون فارغة بعد نجاح تنفيذ العملية بتنفيذ الأمر: $ helm list يظهر الخرج التالي ليشير إلى نجاح العملية: NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION نستطيع إعادة استخدام اسم الإصدار في المستقبل لأنه أصبح متاحًا. الخطوة 6- إنشاء مخططات مخصصة -خطوة اختيارية نعمل على إنشاء مخطط مخصص يتضمن تعريف الموارد وكيفية تحزيم هذه المخططات من أجل إعادة استخدامها لاحقًا. ننشئ مخططًا جديدًا يُدعى "example-chart" بتنفيذ الأمر التالي: $ helm create example-chart ينشئ ذلك مجلّدًا جديدًا يدعى "example-chart" يحتوي المجلدات ضمن البنية التالية: charts/ templates/ ├─ tests/ │ ├─ test-connection.yaml ├─ deployment.yaml ├─ hpa.yaml ├─ ingress.yaml ├─ NOTES.txt ├─ service.yaml ├─ serviceaccount.yaml ├─ _helpers.tpl Chart.yaml values.yaml توجد تعريفات الموارد التي ثبتّها المخطط على العنقود الهدف في المجلد "templates"، إذ ينشئ مدير الحزم Helm مجموعة من التعريفات الافتراضية مثل نقطة بداية لتنشر متحكم "Nginx ingress". نستخدم هنا صيغة قولبة Go على الرغم من أنّ لاحقة الملف هي "YAML"، لتبقى قابلة للتخصيص عبر المتغيرات التي يمكن تمريرها عند تنفيذ الأمر. نتحقق من ذلك بإظهار محتوى الملف "service.yaml" بتنفيذ الأمر التالي: $ cat example-chart/templates/service.yaml نلاحظ وجود أوامر قولية تولّد قيم محاطة بأقواس مضاعفة كما في الخرج التالي: apiVersion: v1 kind: Service metadata: name: {{ include "mychart.fullname" . }} labels: {{- include "mychart.labels" . | nindent 4 }} spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} targetPort: http protocol: TCP name: http selector: {{- include "mychart.selectorLabels" . | nindent 4 }} تُعرض المتغيرات المرجعية للمستخدم وتُعرّف ضمن الملف "values.yaml"؛ وتُخزن نصوص "NOTES" التي يظهرها مدير الحزم Helm ضمن الملف "NOTES.txt" ويجري قولبتها؛ كما تُعرّف بيانات التعريف للمخطط، مثل الاسم و النسخة ونسخة البرمجيات المنشورة ضمن الملف "Chart.yaml"، الذي يتضمن المحتوى التالي: apiVersion: v2 name: mychart description: A Helm chart for Kubernetes … type: application … version: 0.1.0 … appVersion: "1.16.0" نتحقق مما سينشره Helm بتمرير dry-run-- و debug-- للأمر helm install مع الإشارة إلى المجلّد الذي يحتوي المخطط: $ helm install example-chart --dry-run --debug ./example-chart يظهر خرج طويل يتضمن جميع تعريفات الموارد التي تطبق على العنقود أثناء العمل على المخطط، كما يمكن استخدام upgrade helm لدفع النسخة الجديدة الى Kubernetes. $ helm package ./example-chart يظهر خرجٌ مشابهٌ لما يلي: Successfully packaged chart and saved it to: …/example-chart-0.1.0.tgz نستطيع تثبيت المخطط المحزّم كما نثبّت أي مخطط من المخازن المضافة إلى مدير الحزم Helm: $ helm install example-chart example-chart-0.1.0.tgz الخاتمة قدم هذا المقال طريقة استخدام مدير الحزم Helm لتثبيت وترقية البرمجيات المنشورة إلى عنقود Kubernetes، كما أضفنا مخازن المخططات واستخدمنا موقع ArtifactHub للمساعدة في إيجادها، وأنشأنا مخططا مخصصًا جديدًا وتحكمنا بمراجعات الإصدار وبيّنا طريقة التراجع عن الإصدار إذا اقتضى الأمر. ترجمة وبتصرف للمقال How To Install Software on Kubernetes Clusters with the Helm 3 Package Manager لمؤلفيه Savic و Brian Boucheron. اقرأ أيضًا مدخل إلى Helm: مدير حزم Kubernetes ما الفرق بين دوكر Docker وكوبيرنيتيس Kubernetes؟ تعلم أساسيات Kubernetes نظام كوبيرنتس Kubernetes وكيفية عمله
  11. نعرّف الاحتواء ضمن حاوية Containerization على أنه عملية تكييف التطبيق ومكوناته لتصبح قادرة على العمل ضمن بيئة بسيطة أساسية المقومات ندعوها الحاوية لتشكّل بيئة معزولة يمكن التخلص منها بسهولة عند الرغبة بذلك، كما يمكن الاستفادة منها لتطوير واختبار ونشر التطبيقات ضمن بيئات الإنتاج. نعمل في هذا المقال على استخدام أداة Docker Compose لاحتواء تطبيق لارافيل بهدف تطويره ضمن بيئة مستقلة خاصة به. نحصل على تطبيق لارافيل توضيحي موزّع على ثلاث حاويات خدمة منفصلة كما يلي: خدمة تطبيق "app" تعمل على PHP7.4-FPM. خدمة قاعدة بيانات "db" تحتوي خادم MySQL 5.7. خدمة "nginx" تستخدم خدمة "app" من أجل تحليل شيفرة برمجية بلغة PHP قبل تقديم تطبيق لارافيل للمستخدم النهائي. نستخدم وحدات التخزين المشتركة Shared Volumes من أجل مزامنة ملفات التطبيق وذلك لتطوير تطبيق بسيط وتصحيح الأخطاء بسهولة، كما نستخدم أوامر "docker-compose exec" لتشغيل تعليمات "Composer" و "Artisan" في حاوية التطبيق. المتطلبات الأساسية الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو Ubuntu (استعملنا الإصدار 18.04 في هذا المقال) أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo، ولا يُفضّل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم، كما يُفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت الأداة دوكر على الخادم أو الجهاز المحلي. تثبيت أداة دوكر كومبوز "Docker Compose" على الخادم أو الجهاز المحلي. الخطوة 1- الحصول على التطبيق التوضيحي نبدأ بتحميل تطبيق لارافيل التوضيحي من مخزن Github وننتقل إلى الفرع tutorial-01 والذي يتضمن تطبيقًا بسيطًا مبنيًا باستخدام لارافيل. نعتمد في هذا العمل على الإصدار tutorial-1.0.1 والذي نحملّه ضمن المجلد الأساسي للمستخدم بتنفيذ الأمر: cd ~ curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip يبدأ تحميل الملف المضغوط بصيغة "zip" لذلك يجب عند انتهاء التحميل فك الضغط بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا كما يجب تثبيت الأداة "unzip" لتحقيق ذلك. ننفذ الأمر التالي: sudo apt update sudo apt install unzip ننفذ الأمر التالي لفك الضغط وتسمية المجلد ليصبح باسم "travellist-demo" بهدف السهولة: unzip travellist.zip mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo ننتقل إلى المجلد "travellist-demo" من خلال الأمر التالي: cd travellist-demo الخطوة 2- إعداد ملف الضبط الخاص بالتطبيق تتواجد ملفات ضبط لارافيل في مجلد يُدعى "config" ضمن مجلد الجذر للتطبيق، إذ يُستخدم الملف "env." لعمليات الضبط المتعلقة بالبيئة، مثل بيانات الاعتماد وأية معلومات تختلف بين عمليات نشر التطبيقات لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا. تحذير: يحتوي ملف تهيئة البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب أبدًا مشاركة هذا الملف علنًا. توجد أولوية للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config". تتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات جديدة، مثل إعدادات الاتصال في قاعدة البيانات، وخيارات التصحيح، ورابط URL للتطبيق، إضافةً لبقية العناصر او المعلومات التي تختلف تبعًا للبيئة التي يعمل بها التطبيق. ننشئ ملف "env." جديد لضبط خيارات التهيئة لبيئة التطوير التي نُعدها. ويمكننا نسخ الملف "example.env" المتاح افتراضيًا مع أي تطبيق لارافيل بتنفيذ الأمر: cp .env.example .env نحرر الملف باستخدام محرر النصوص نانو "nano" أو باختيار محرر النصوص المفضّل: nano .env يحتوي ملف "env." الحالي من تطبيق "travellist" التوضيحي على إعدادات لاستخدام التطبيق المُحتَوى المتصل بقاعدة بيانات محلية من نوع MySQL أي أنها متاحة على المضيف المحلي"127.0.0.1"، نحتاج لتعديل قيمة المتغير DB_HOST لكي يشير إلى قاعدة البيانات التي ننشئها ضمن بيئة دوكر. نعتمد في عملنا على أنّ إسم خدمة قواعد البيانات هو "db". نعدّل محتوى الملف لضبط قيم المتغيرات على النحو التالي: APP_NAME=Travellist APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=password ... نستطيع تغيير القيم الخاصة ببقية المتغيرات مثل اسم قاعدة البيانات وكلمة المرور واسم المستخدم عند إعداد الملف "docker-compose.yml" من أجل تهيئة الخدمات. نضغط على الاختصار "CTRL + X" ثم الحرف "Y" وأخيرًا زر الإدخال "Enter" بعد الانتهاء من تعديل الملف. الخطوة 3- إعداد Dockerfile للتطبيق تستند خدمتا MySQL و Nginx إلى الصور الافتراضية التي يمكن الحصول عليها من Docker Hub، ونحتاج في مثالنا إلى إنشاء صورة مخصصة لحاوية التطبيق وسننشئ ملف Dockerfile جديد لذلك. تعتمد صورة التطبيق travillist على صورة PHP الرسمية ذات الاسم "php:7.4-fpm" والمتاحة ضمن مخزن Docker Hub. نحتاج تثبيت بعض حزم PHP الإضافية باستخدام أداة إدارة الاعتمادية Composer. ننشئ مستخدم نظام جديد لتنفيذ الأوامر المختلفة مثل أوامر "composer" و "artisan" أثناء تطوير التطبيق. يضمن إعداد "uid" امتلاك المستخدم الموجود داخل الحاوية نفس معرف المستخدم الخاص بمستخدم النظام على الجهاز المضيف أثناء تشغيل دوكر. تتزامن الملفات التي تُنشأ من الأوامر في جهاز المضيف باستخدام الأذونات الصحيحة، نستطيع استخدام أي محرر نصوص لتطوير الشيفرة البرمجية للتطبيق داخل الحاويات. ننشئ ملف Dockerfile جديد بتنفيذ الأمر: nano Dockerfile ننسخ المحتوى التالي إلى ملف Dockerfile: FROM php:7.4-fpm # Arguments defined in docker-compose.yml ARG user ARG uid # Install system dependencies RUN apt-get update && apt-get install -y \ git \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Create system user to run Composer and Artisan Commands RUN useradd -G www-data,root -u $uid -d /home/$user $user RUN mkdir -p /home/$user/.composer && \ chown -R $user:$user /home/$user # Set working directory WORKDIR /var/www USER $user نحفظ الملف بعد الانتهاء من التعديل عليه. يبدأ الملف بتحديد الصورة الأساس التي نستخدمها وهي في حالة الملف السابق php:7.4-fpm. نثبت كومبوزر بنسخ الملف التنفيذي الخاص بـ composer والمتاح ضمن أحدث صورة رسمية إلى صورة التطبيق الخاص بنا. ننشئ مستخدم نظام جديد ونبدأ بإعداد المتغيرين user و uid الذين عرّفناهما في بداية الملف Dockerfile إذ تُمرر هذه المتغيرات إلى الحاوية باستخدام الأداة دوكر كومبوز في وقت الإنشاء. نحدد مسار العمل الافتراضي "www/var/" ونسجل الدخول بواسطة المستخدم الذي أنشأناه مؤخرًا، للتأكد من الاتصال بقاعدة البيانات مثل مستخدم عادي وأننا في المسار الصحيح عند استخدام الأوامر مثل أوامر "composer" و "artisan" في حاوية التطبيق. الخطوة 4- إعداد بنية خادم Nginx وملفات تفريغ قاعدة البيانات يجب مشاركة ملفات الضبط أو التهيئة مع حاويات الخدمة عند إنشاء بيئة تطوير باستخدام الأداة دوكر كومبوز مما يسهّل إجراء التعديلات على ملفات الضبط وضبط البيئة أثناء تطوير التطبيق. ننشئ مجلد ونضع به الملفات التي تُستخدم في تهيئة وضبط حاويات الخدمة. ننشئ مجلد "docker-compose/nginx" ونضع به ملف "travellist.conf" الذي يهيئ آلية تقديم التطبيق وذلك بتنفيذ الأمر: mkdir -p docker-compose/nginx نعدل محتوى الملف "travellist.conf" باستخدام محرر النصوص المفضل عن طريق تنفيذ الأمر التالي: nano docker-compose/nginx/travellist.conf نضيف الشيفرة البرمجية التالية داخله: server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; 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 / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } يضبط الملف السابق خادم Nginx ويجبره على الاستماع للمنفذ "80" ويستخدم الصفحة index.php لتكون صفحة الدليل الأساسية للتطبيق. نضبط المسار الجذر Root للمستند ليصبح var/www/public/ ونضبط Nginx ونجبره على استخدام المنفذ "9000" لمعالجة الملفات ذات اللاحقة "php.*". سنشارك تفريغ قاعدة البيانات database dumpfile التي تستورد عند تهيئة الحاوية لإعداد قاعدة البيانات MySQL، إذ تتوفر هذه الميزة في MySQL 5.7 التي سنستخدمها في حاوية التطبيق. ننشئ مجلدًا جديدًا لتهيئة ملفات MySQL داخل المجلد "docker-compose" بتنفيذ الأمر التالي: mkdir docker-compose/mysql ننشئ ملف "sql." جديد بتنفيذ الأمر: nano docker-compose/mysql/init_db.sql يعتمد ملف قاعدة البيانات MySQL dump التالي على قاعدة البيانات المُنشأة في مقال لارافيل بالاعتماد على LEMP من ديجيتال أوشن، إذ يُنشئ جدولًا اسمه places في قاعدة البيانات ثم سيملأ محتوياته بمجموعة من العينات. ولضبط بنية هذا الجدول ومحتوياته، نكتب الشيفرة البرمجية التالية في الملف "init_db.sql" ليصبح كما يلي: DROP TABLE IF EXISTS `places`; CREATE TABLE `places` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `visited` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0); يتضمن الجدول places ثلاثة حقول id و name و visited وهي على الترتيب معرّف خاص بكل مكان واسم المكان ومتغير يشير إلى زيارة المكان مسبقًا أم لا، ويمكن تعديل أسماء الحقول وإضافة حقول جديدة عند الحاجة. الخطوة 5- إنشاء بيئة متعددة الحاويات باستخدام أداة دوكر كومبوز تٌنشئ أداة دوكر كومبوز بيئات متعددة الحاويات للتطبيقات التي تعمل على دوكر، كما يستخدم تعريفات الخدمة لبناء بيئات قابلة للتخصيص بالكامل مع حاويات متعددة يمكنها مشاركة الشبكات وأحجام البيانات، مما يتيح التكامل السلس بين مكونات التطبيق المختلفة. ننشئ ملفًا جديدًا يسمى "docker-compose.yml"، والذي يمكن أن يكون موجودًا مسبقًا ضمن مجلد الجذر Root للتطبيق، ويحدد هذا الملف بيئة الحاويات بما في ذلك الصور الأساسية لبناء التطبيق وكيفية تفاعل الخدمات ضمنه. نحدد ثلاث خدمات مختلفة ضمن ملف "docker-compose.yml" وهي "app" و "db" و "nginx"؛ إذ تُنشئ خدمة "app" صورةً تسمى "travellist" بناءً على ملف Dockerfile الذي أنشأناه مسبقًا، وتُشغّل الحاوية التي تحددها هذه الخدمة خادم "php-fpm" لتحليل شيفرات PHP وتُرسل النتائج مرةً أخرى إلى خدمة "nginx"، التي تعمل على حاوية منفصلة؛ بينما تحدد خدمة "mysql" حاويةً تُشغل خادم MySQL 5.7. تتصل هذه الخدمات فيما بينها باستخدام شبكة جسر أسميناها "travellist". تُزامن ملفات التطبيق على كل من الخدمتين "app" و "nginx" عبر حوامل الربط ؛ إذ تُعد حوامل الربط مفيدةً في بيئات التطوير لأنها تتيح مزامنةً ثنائية الاتجاه بين الجهاز المضيف والحاويات. نُنشئ ملفًا جديدًا باسم "docker-compose.yml" في مجلد الجذر Root للتطبيق بتنفيذ الأمر التالي: nano docker-compose.yml يبدأ ملف "docker-compose.yml" التقليدي برقم الإصدار يليه تعريف الخدمات "services" الخاصة بالتطبيق، كما يُضاف تعريف الشبكات التي يشاركها التطبيق في نهاية الملف، ويكون بالتالي محتوى هذا الملف على النحو التالي: version: "3.7" services: networks: travellist: driver: bridge خدمة التطبيق app تُعِد الخدمة "app" حاويةً باسم "travellist-app" وتبني صورة دوكر جديدة بناءً على Dockerfile الموجود في نفس مسار الملف "docker-compose.yml" وتُحفظ الصورة محليًا باسم "travellist". نحتاج تواجد ملفات التطبيق ضمن حاوية التطبيق "app" حتى ولو كانت هذه الملفات موجودةً في جذر المستند الذي قد جرى تقديمه على أنه تطبيق موجود في حاوية "nginx"، ونحتاج ذلك من أجل تنفيذ أوامر أداة "Artisan" الخاصة بإطار عمل لارافيل على هذه الملفات. نضيف تعريف الخدمة التالي إلى الملف "docker-compose.yml": app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist تحقق هذه الإعدادات ما يلي: build: تُعلِم هذه البنية الأداة دوكر كومبوز ببناء صورة محلية لخدمة التطبيق، باستخدام المسار المحدد context وملف Dockerfile للحصول على الإرشادات. تُحقن المتغيرات user و uid في Dockerfile لتخصيص أوامر إنشاء المستخدم في وقت الإنشاء. image: تُعد الاسم الذي يستخدم للصورة قيد الإنشاء. container_name: تُعِد اسم الحاوية لهذه الخدمة. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف الخدمة. working_dir: يعيّن المجلّد الافتراضي لهذه الخدمة مثل var/www/. volumes: يُنشئ وحدة تخزين مشتركة تُزامِن المحتويات من المسار الحالي إلى var/www/ داخل الحاوية، ويبقى موجودًا في حاوية "nginx". networks: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. خدمة قاعدة البيانات db تستخدم خدمة "db" صورة MySQL 5.7 من Docker Hub. نظرًا لأن دوكر كومبوز يحمّل الملفات المتغيرة "env." الموجودة في نفس المسار الذي يحتوي الملف "docker-compose.yml"، نحصل على إعدادات قاعدة البيانات ملف "env." الذي قد ولّدناه عند إنشاء تطبيق لارافيل. نضع البيانات التالية بعد البيانات التي وضعناها للخدمة "app": db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: تحدد صورة دوكر التي ستُستخدم في هذه الحاوية. نستخدم صورة MySQL 5.7 من Docker Hub. container_name: اسم الحاوية travellist-db. restart: يعيد التشغيل دائمًا ، ما لم يحدث إيقاف الخدمة. environment: تُحدد متغيرات البيئة في الحاوية الجديدة. نستخدم القيم التي حصلنا عليها من ملف "env." لإعداد خدمة قاعدة البيانات MySQL والتي تُنشِئ تلقائيًا قاعدة بيانات ومستخدمًا جديدًا بناءً على متغيرات البيئة المتوفرة. volumes: ينشئ وحدة تخزين لتهيئة قاعدة بيانات التطبيق. تستورد صورة قاعدة البيانات MySQL ملفات"sql." تلقائيًا والتي توجد في المسار ‎/docker-entrypoint-initdb.d داخل الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. خدمة nginx تستخدم خدمة "nginx" صورة Nginx مبنية مسبقًا على توزيعة لينكس اسمها Alpine، إذ تنشئ حاويةً باسم "travellist-nginx" وتُعيد التوجيه من المنفذ "8000" الى المنفذ "80" داخل الحاوية. نضع البيانات التالية بعد بيانات خدمة "db": nginx: image: nginx:1.17-alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: اسم صورة دوكر التي تستخدم في هذه الحاوية وهي في هذه الحالة الصورة Alpine Nginx 1.17 . container_name: اسم الحاوية travellist-nginx. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف الخدمة. ports: تعيد توجيه المنفذ الذي يسمح بالوصول الخارجي عبر المنفذ "8000" إلى خادم الويب الذي يعمل على المنفذ 80 داخل الحاوية. volumes: تنشئ وحدتي تخزين مشتركتين، بحيث تزامن الوحدة الأولى المحتويات من نقطة العمل إلى المسار var/www/ داخل الحاوية ويفيد ذلك بنقل التعديلات المحلية إلى التطبيق الذي يقدّمه Nginx تلقائيًا، وتنسخ الوحدة الثانية ملفات الإعداد الخاصة بخادم nginx الموجودة في الملف "docker-compose/nginx/travellist.conf" الى ملفات الضبط الخاصة بـ nginx ضمن الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. وعليه يصبح ملف "docker-compose.yml" على النحو التالي: version: "3.7" services: app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist nginx: image: nginx:alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d/ networks: - travellist networks: travellist: driver: bridge الخطوة 6- تشغيل التطبيق باستخدام أداة دوكر كومبوز ننشئ صورة تطبيق جديد ونشغّل الخدمات التي حددناها ضمن الإعدادات باستخدام الأمر التالي: docker-compose build app يستغرق الأمر بضعة دقائق ومن ثم يظهر الخرج التالي: Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest نُشغّل البيئة بالخلفية بعد الانتهاء من مرحلة الإنشاء بتنفيذ الأمر: docker-compose up -d ويكون الخرج على النحو التالي: Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done نستعرض معلومات حالة الخدمة النشطة حاليًا بتنفيذ الأمر: docker-compose ps ويكون الخرج على النحو التالي: Name Command State Ports ------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp بيئتنا الآن قيد التشغيل، لكننا ما زلنا بحاجة إلى تنفيذ أمرين لإنهاء إعداد التطبيق، إذ نستخدم الأمر docker-compose exec لتنفيذ جميع الأوامر ضمن الحاويات، فلو رغبنا بتنفيذ الأمر ls –l الذي يظهر معلومات تفصيلية حول الملفات في مسار التطبيق، ننفذ الأمر التالي وتظهر النتائج كما يلي: docker-compose exec app ls -l ويكون الخرج على النحو التالي: total 256 -rw-rw-r-- 1 sammy 1001 738 Jan 15 16:46 Dockerfile -rw-rw-r-- 1 sammy 1001 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy 1001 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy 1001 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy 1001 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy 1001 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy 1001 4096 Jan 15 16:46 docker-compose -rw-rw-r-- 1 sammy 1001 1015 Jan 15 16:45 docker-compose.yml -rw-rw-r-- 1 sammy 1001 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy 1001 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy 1001 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy 1001 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy 1001 4096 Jan 7 08:05 tests -rw-rw-r-- 1 sammy 1001 538 Jan 7 08:05 webpack.mix.js تُثبّت اعتماديات التطبيق باستخدام الأداة composer install كما يلي: docker-compose exec app composer install يظهر الخرج التالي بعد إتمام العملية: Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. نولّد مفتاح التطبيق الخاص باستخدام أداة artisan الخاصة بلارافيل، إذ يشفّر هذا المفتاح جلسات المستخدم والبيانات الحساسة: docker-compose exec app php artisan key:generate ويكون الخرج على النحو التالي: Application key set successfully. نطلب الرابط التالي من المتصفح: http://server_domain_or_IP:8000 يظهر عندها الخرج التالي: نستطيع استخدام الأمرlogs لفحص السجلات التي تولّدها الخدمة بتنفيذ الأمر التالي: docker-compose logs nginx ويكون الخرج على النحو التالي: Attaching to travellist-nginx travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:25 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:26 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:42 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" … نستطيع إيقاف العمل مؤقتًا لبيئة دوكر كومبوز مع الحفاظ على حالة الخدمات بتشغيل الأمر: Docker-compose puse ويكون الخرج على النحو التالي: Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done نستطيع استئناف العمل بتنفيذ الأمر: docker-compose unpause ويكون الخرج على النحو التالي: Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done نستطيع إيقاف عمل بيئة كومبوز ونزيل جميع حاوياتها وشبكاتها ووحدات تخزينها بتنفيذ الأمر: docker-compose down ويكون الخرج على النحو التالي: Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist الخاتمة أعددنا بيئة دوكر مكونة من ثلاث حاويات باستخدام الأداة دوكر كومبوز وحددنا بنيته الأساسية في ملف YAML. يمكن العمل على تطبيق لارافيل دون الحاجة إلى تثبيت خادم ويب محلي وإعداده للتطوير والاختبار، ويتحقق كل ذلك باستخدام بيئة معزولة يمكن تكرارها وإعادة إنشائها بسهولة حتى الوصول إلى التطبيق المطلوب تثبيته ضمن بيئات الإنتاج. ترجمة -وبتصرّف- للمقال How To Containerize a Laravel Application for Development with Docker Compose on Ubuntu 18.04 لصاحبه Erika Heidi. اقرأ أيضًا تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose كيفية تثبيت Docker Compose على دبيان نقل سير عمل Docker Compose إلى Kubernetes إعداد لارافيل مع خادم Nginx وقاعدة بيانات MySQL باستخدام دوكر كومبوز Docker Compose
  12. تتضمن العديد من تطبيقات الويب نظام إشعارات مبني ضمن التطبيق والذي يُعلِم المستخدم فورًا عندما يحاول شخص ما تنفيذ فعل ما مرتبط به، إذ يتلقى المستخدم في شبكة التواصل الاجتماعي فيسبوك مثلًا إشعارًا عندما يُعجَبُ أحدهم بحالة ما قد نشرها المستخدم أو عندما يضع أحدهم تعليقًا على صفحة المستخدم الشخصية. ننشئ في هذه المقالة آليةً شبيهةً بذلك عن طريق تطوير منظومة إشعارات معتمدة على الويب باستخدام بيئة لارافيل ومكتبة Pusher. المتطلبات الأساسية يجب التأكد من تثبيت خادم PHP ولارافيل Laravel على الحاسوب لإكمال المشروع كما يجب امتلاك حساب على منصة بوشر Pusher. ما الذي سنبنيه؟ يتضمن العمل إنشاء تطبيق ويب بسيط يعرض الإشعارات باستخدام لارافيل وقنوات بوشر Pusher. يبين العرض التالي ما الذي نريد بناءه: إعداد تطبيق Pusher ننشئ بدايةً حسابًا على منصة Pusher ومن ثم نضبط التطبيق كما هو موضح بالصورة أدناه: إعداد تطبيق لارافيل ننشئ تطبيق لارافيل جديد بإجراء الأمر التالي في موجه الأوامر: laravel new laravel-web-notifications نثبت حزمة التطوير البرمجي الخاصة بمنصة بوشر Pusher والمعتمدة على لغة PHP بتنفيذ الأمر التالي: composer require pusher/pusher-php-server نوجّه لارافيل لاستخدام منصة بوشر على أنها وسيلة لإرسال رسائل بث broadcast تُستخدم لإعلام أجزاء البرنامج بوقوع حدثٍ ما، ولتحقيق ذلك نفتح الملف "‎.env" الموجود في المجلد الجذر Root الخاص بلارافيل، ثم نحدّث محتواه ليوافق الضبط التالي مع ضرورة استبدال الرموز X بالقيم الخاصة بالحساب الخاص بك: PUSHER_APP_ID=322700 BROADCAST_DRIVER=pusher // ‫نضيف المعلومات المتعلقة بالحساب الخاص بنا من منصة بوشر PUSHER_APP_ID=XXXXX PUSHER_APP_KEY=XXXXXXX PUSHER_APP_SECRET=XXXXXXX ملاحظة مهمة: يتصل لارافيل افتراضيًا بخوادم الولايات المتحدة الأمريكية، وعند الحاجة لاستخدام خوادم أخرى، يجب تحديث مصفوفة الخيارات الموجودة ضمن الملف "config/broadcasting.php"، كما يُعدّل الملف "config/app.php" ويحذف التعليق الموجود في الجزء: App\Providers\BroadcastServiceProvider::class إنشاء التطبيق الذي يدمج لارافيل مع Pusher ننشئ التطبيق بعد الانتهاء من العمليات السابقة، حيث نبدأ بإنشاء صنف الحدث Event، الذي يبث الرسائل إلى قنوات بوشر Pusher انطلاقًا من تطبيق لارافيل. تُستدعى الأحداث من أي مكان نرغب به ضمن التطبيق. php artisan make:event StatusLiked ينشئ هذا السطر صنفًا باسم StatusLiked ضمن مجلد "app/Events". نفتح هذا الملف ونحدّث محتواه كما يلي: <?php namespace App\Events; use Illuminate\Queue\SerializesModels; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class StatusLiked implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $username; public $message; /** * إنشاء عينة جديدة من الحدث * * @return void */ public function __construct($username) { $this->username = $username; $this->message = "{$username} liked your status"; } /** * تحديد القنوات التي سيُبث الحدث عليها * * @return Channel|array */ public function broadcastOn() { return ['status-liked']; } } تخبر الواجهة ShouldBroadcast لارافيل أن الحدث الحالي يجب أن يُرسل وفقًا للطريقة المحدّدة في ملف الضبط الذي أعددناه مسبقًا. يوجد تابع باني يأخذ وسيطين، هما: اسم المستخدم وفعل verb، إذ تُسند قيم المتغيرات إلى خصائص الصنف التي تأخذ نفس الأسماء، ويجب أن تكون هذه الخصائص عامة public وإلا فسيجري تجاهلها. إنشاء واجهة عرض التطبيق نستخدم واجهة عرض وحيدة تحتوي شريط تنقّل وأيقونة للإشعارات، إذ تُحدّث الأيقونة عند وجود إشعارات جديدة دون الحاجة لإعادة تحميل الصفحة. لن تستمر الإشعارات طويلًا في التجربة الحالية ولكن يمكن زيادة المدة الزمنية لاستمرار الإشعار حسب الحاجة. نفتح الملف "welcome.blade.php" ونستبدل محتواه بما يلي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Demo Application</title> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="/css/bootstrap-notifications.min.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-9" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Demo App</a> </div> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="dropdown dropdown-notifications"> <a href="#notifications-panel" class="dropdown-toggle" data-toggle="dropdown"> <i data-count="0" class="glyphicon glyphicon-bell notification-icon"></i> </a> <div class="dropdown-container"> <div class="dropdown-toolbar"> <div class="dropdown-toolbar-actions"> <a href="#">Mark all as read</a> </div> <h3 class="dropdown-toolbar-title">Notifications (<span class="notif-count">0</span>)</h3> </div> <ul class="dropdown-menu"> </ul> <div class="dropdown-footer text-center"> <a href="#">View All</a> </div> </div> </li> <li><a href="#">Timeline</a></li> <li><a href="#">Friends</a></li> </ul> </div> </div> </nav> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script src="//js.pusher.com/3.1/pusher.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script type="text/javascript"> var notificationsWrapper = $('.dropdown-notifications'); var notificationsToggle = notificationsWrapper.find('a[data-toggle]'); var notificationsCountElem = notificationsToggle.find('i[data-count]'); var notificationsCount = parseInt(notificationsCountElem.data('count')); var notifications = notificationsWrapper.find('ul.dropdown-menu'); if (notificationsCount <= 0) { notificationsWrapper.hide(); } // ‫تأهيل وظيفة السجلات الخاصة بمكتبة بوشر Pusher // لا نستخدم هذه الوظيفة في بيئة الإنتاج الفعلية // Pusher.logToConsole = true; var pusher = new Pusher('API_KEY_HERE', { encrypted: true }); // الإشتراك بالقناة التي حددناها في صنف الحدث المعرّف في لارافيل var channel = pusher.subscribe('status-liked'); // ربط تابع ما بالحدث الذي عرّفناه في الصنف channel.bind('App\\Events\\StatusLiked', function(data) { var existingNotifications = notifications.html(); var avatar = Math.floor(Math.random() * (71 - 20 + 1)) + 20; var newNotificationHtml = ` <li class="notification active"> <div class="media"> <div class="media-left"> <div class="media-object"> <img src="https://api.adorable.io/avatars/71/`+avatar+`.png" class="img-circle" alt="50x50" style="width: 50px; height: 50px;"> </div> </div> <div class="media-body"> <strong class="notification-title">`+data.message+`</strong> <!--p class="notification-desc">Extra description can go here</p--> <div class="notification-meta"> <small class="timestamp">about a minute ago</small> </div> </div> </div> </li> `; notifications.html(newNotificationHtml + existingNotifications); notificationsCount += 1; notificationsCountElem.attr('data-count', notificationsCount); notificationsWrapper.find('.notif-count').text(notificationsCount); notificationsWrapper.show(); }); </script> </body> </html> نركّز على الجزء الخاص بلغة جافا سكريبت JavaScript، الذي يتضمن الأجزاء الخاصة بمكتبة Pusher التي ترسل الإشعارات. وفيما يلي الجزء المهم من الكتلة البرمجية الخاصة بعملية الإرسال: // ‫تأهيل وظيفة السجلات الخاصة بمكتبة بوشر //لا نستخدم هذه الوظيفة في بيئة الإنتاج الفعلية // Pusher.logToConsole = true; // نهيئ مكتبة جافا سكريبت الخاصة بقنوات بوشر var pusher = new Pusher('API_KEY_HERE', { encrypted: true }); // الإشتراك بالقناة التي حددناها في صنف الحدث المعرّف في لارافيل var channel = pusher.subscribe('status-liked'); // ربط تابع ما بالحدث الذي عرّفناه في الصنف channel.bind('App\\Events\\StatusLiked', function(data) { // يُستدْعى هذا التابع عند استلام إشعار بالحدث }); ملاحظة: ستبث لارافيل الحدث افتراضيًا تحت اسم الصنف الخاص بالحدث ولكن يمكن تخصيص هذا الاسم عن طريق تعريف طريقة خاصة للبث الخاص بالحدث: public function broadcastAs() { return 'event-name'; } تهيئ الشيفرة السابقة مكتبة الجافا سكريبت الخاصة بالتعامل مع بوشر Pusher وتؤسس قناة اتصال لإرسال واستقبال الأحداث المختلفة، وتتضمن أيضًا طريقةً خاصةً تُستَدعى عند استلام عملية بث تخص حدث ما عن طريق القناة. اختبار التطبيق ننشئ الاتجاه Route اللازم لتنفيذ الحدث والذي يسبب وصول الإشعار إلى المستخدم، إذ يظهر الإشعار عند الوصول إلى هذا الاتجاه ما لم يوجد خطأ ما في الخطوات السابقة. نضيف الاتجاه الجديد كما يلي: Route::get('test', function () { event(new App\Events\StatusLiked('Someone')); return "Event has been sent!"; }); نشغّل خادم PHP عن طريق لارافيل لاختبار نجاح عمل البرنامج الذي كتبناه: php artisan serve الخاتمة أنشأنا نظام إشعارات خاص بالويب باستخدام عددٍ قليل نسبيًا من السطور البرمجية بالاعتماد على قنوات بوشر Pusher، وما أنجزناه يُعد مثالًا بسيطًا على قدرات هذه المكتبة وأداةً يمكن تضمينها في عدة مشاريع، ولا شك أنه يمكن الاعتماد على مكتبة بوشر Pusher في تطوير كثيرٍ من الأدوات المفيدة أيضًا والتي يمكن تضمينها ضمن مختلف المشاريع البرمجية. ترجمة -وبتصرف- للمقال How To Create Web Notifications Using Laravel and Pusher Channels لصاحبه Neo Ighodaro. اقرأ أيضًا أساسيات بناء التطبيقات في إطار العمل Laravel 5 إنشاء تطبيق Todo List بسيط باستخدام Laravel 5 - الجزء الأول
  13. يُعد دوكر الحل الأكثر شيوعًا لنشر التطبيقات بسبب ما يقدمه من تبسيط لعملية تشغيل التطبيقات ونشرها في حاويات مؤقتة. يمكن استخدام دوكر لإنشاء حاويات تشكل حزمة تطبيقات LEMP مع خوادم PHP و Nginx و MySQL وإطار عمل لارافيل من أجل تسهيل عملية إنشاء التطبيقات. يسمح Docker Compose للمطورين بتعريف البنية التحتية بما فيها من خدمات وشبكات ووحدات تخزين في ملف واحد ويوفر بديلًا فعالًا لتشغيل الأمرين التاليين: docker container create docker container run سننشئ تطبيقًا باستخدام إطار عمل لارافيل، مع خادم ويب Nginx وقاعدة بيانات MySQL، إذ تتواجد هذه المكونات ضمن حاويات دوكر، وسنحدد تكوين المكدس كاملًا ضمن ملف "docker-compose"، جنبًا إلى جنب مع ملفات التهيئة للغة PHP وقاعدة بيانات MySQL وخادم Nginx. المتطلبات الأساسية الوصول إلى خادم يعمل بنظام التشغيل أوبنتو Ubuntu ذي رقم إصدار 18.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر root لأسباب تتعلق بأمان الخادم، كما يُفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت الأداة دوكر على الخادم. تثبيت الأداة دوكر كومبوز Docker Compose على الخادم. الخطوة 1- تنزيل لارافيل وتثبيت اعتمادياتها لا بُد من تنزيل أحدث إصدار متاح من لارافيل وتثبيت الاعتماديات اللازمة للمشروع البرمجي بما فيها Composer، مدير الحزم الخاص بلغة PHP في دوكر. نثبّت أحدث إصدار من لارافيل داخل مجلد laravel-app ضمن المسار الرئيسي للنظام كما يلي: cd ~ git clone https://github.com/laravel/laravel.git laravel-app ننتقل إلى المجلّد الجديد: cd ~/laravel-app نستخدم صورة composer لمشاركة المجلدات التي نحتاجها ضمن مشروع لارافيل ويفيدنا ذلك أيضًا بتجنب أعباء تثبيت الأداة Composer عمومًا ضمن الخادم. ننفذ الأمر التالي لتحقيق ذلك: docker run --rm -v $(pwd):/app composer install تُنشئ التعليمة السابقة باستخدام الرايات v- و rm– حاويةً تزول تلقائيًا عند الانتهاء من عملها أي عندما ينفذ المستخدم الأمرexit، وتُربط بالمسار الحالي قبل إزالتها، وسينسخ هذا محتويات مسار التطبيق "laravel-app/~" إلى الحاوية، ويضمن نسخ المجلد "vendor" الذي أنشأه Composer داخل الحاوية إلى المسار الحالي. نضبط أذونات التطبيق على أنه مستخدم غير جذر non-root: sudo chown -R $USER:$USER ~/laravel-app سيكون هذا مهمًا عند كتابة Dockerfile لصورة التطبيق الخاص بك في الخطوة 4، إذ سيسمح لك بالعمل مع شيفرة التطبيق الخاصة بك وتشغيل العمليات في الحاوية الخاصة بك مثل مستخدم غير جذر. بعد الانتهاء من كتابة شيفرة التطبيق الخاص بك، يمكنك الانتقال إلى تحديد خدماتك باستخدام دوكر كومبوز. الخطوة 2- إنشاء ملف دوكر كومبوز تُبسّط الأداة دوكر كومبوز عملية إعداد التهيئة الأساسية للبنية التحتية المستخدمة في مشروع تطوير معين مع الاحتفاظ بالتعديلات المختلفة المُطبقة والتي ندعو كل منها إصدارًا. ننشئ ملف "docker-compose" لإعداد تطبيق لارافيل يتضمن إنشاء البيئة اللازمة للتطبيق من خادم الويب وقاعدة البيانات والخدمات الأخرى. nano ~/laravel-app/docker-compose.yml نضبط الخدمات الثلاثة "db" و "webserver" و "app"بإضافة الشيفرة البرمجية التالية الى الملف "laravel-app/docker-compose.yml/~" مع الأخذ بالحسبان ضبط كلمات المرور جيدًا. نتأكد من وضع كلمة المرورMYSQL_ROOT_PASSWORD، بحيث تصبح هذه القيمة متغيرًا خاصًا بكامل البيئة أي ضمن خادم الويب وقاعدة البيانات وخدمات التطبيق المختلفة. نضيف المحتوى التالي إلى الملف "laravel-app/docker-compose.yml/~": version: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: digitalocean.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: your_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql networks: - app-network #Docker Networks networks: app-network: driver: bridge يتضمن هذا الملف تعريف الخدمات التالية: "app": تحدد هذه الخدمة صورة دوكر التي ستُستخدم وتضبط مجلد العمل working_dir في الحاوية ليصبح var/www/. "webserver": تحدد صورة nginx:alpine وتعيّن المنفذين 80 و 443. "db": تنشئ حاوية انطلاقًا من صورة mysql:5.7.22 وتعرّف بعض متغيرات البيئة الأخرى، مثل اسم قاعدة البيانات وكلمة المرور المستخدمة والتي يجب أن تكون مناسبة. تحدد هذه الخدمة أيضًا المنافذ المستخدمة، إذ تربط المنفذ 3306 للمضيف إلى المنفذ 3306 للحاوية. تحدد خاصية container_name اسمًا للحاوية يتوافق مع اسم الخدمة، وإذا لم تحدد هذه الخاصية، يعين دوكر اسمًا لكل حاوية من خلال الجمع بين اسم شخص مشهور تاريخيًا وكلمة عشوائية مفصولة بشرطة سفلية. لتسهيل الاتصال بين الحاويات، تُوصل الخدمات بشبكة جسرية تسمى app-network، إذ تستخدم هذه الشبكة جسرًا برمجيًا Software Bridge يسمح للحاويات المتصلة بنفس الشبكة التواصل مع بعضها بعضًا. يثبّت برنامج تشغيل الجسر Bridge driver آليًا قواعد الاتصال الشبكي على الجهاز المضيف بحيث يضمن عزل الحاويات الموجودة على الشبكات الجسرية المختلفة عن بعضها بعضًا ما لم يرغب المستخدم بربطها معًا. يزيد ذلك من أمان التطبيق ويضمن تواصل الخدمات ذات الصلة فقط مع بعضها بعضًا، وبذلك تستخدم خدمات التطبيقات الأمامية شبكة "frontend" وتستخدم خدمات الواجهة الخلفية شبكة "backend". الخطوة 3- ديمومة البيانات يتضمن دوكر عدة مزايا تضمن احتفاظ أو ديمومة البيانات Data Persistence، ففي تطبيقنا نستخدم وحدات التخزين Volumes وحوامل الربط bind mounts لضمان احتفاظ البيانات ضمن قاعدة البيانات وملفات التطبيق والتهيئة العامة؛ إذ توفر وحدات التخزين المرونة للنسخ الاحتياطي والاستمرار الى ما بعد دورة حياة الحاوية؛ وتسهل حوامل الربط تغيير التعليمات البرمجية أثناء التطوير، مما يزامن إجراء التغييرات على ملفات المضيف والمجلدات في الحاوية لتنعكس هذه التغييرات فور اعتمادها على التطبيق. تحذير: تتيح حوامل الربط إمكانية تغيير نظام ملفات المضيف من خلال العمليات التي تعمل في الحاوية، بما في ذلك إنشاء أو تعديل أو حذف ملفات النظام أو المجلدات المهمة. على الرغم من الفائدة الكبيرة لهذه الميزة إلا أنّ لها انعكاسات أمنية يمكن أن تؤثر على العمليات التي لا تتعلق بدوكر على النظام المضيف لذلك يتوجب استخدام حوامل الربط بعناية. ننشئ وحدة تخزين تدعى dbdata في خدمة db من أجل احتفاظ قاعدة البيانات MySQL بوضع البيانات التالية ضمن ملف docker-compose.yml ... #MySQL Service db: ... volumes: - dbdata:/var/lib/mysql networks: - app-network ... تضمن وحدة التخزين dbdata الاحتفاظ بالمحتوى في المجلد ‎/var/lib/mysql وبذلك يمكن إيقاف وإعادة تشغيل خدمة db دون فقدان البيانات. نضيف في نهاية ملف التعريف التالي لوحدة التخزين dbdata: ... #Volumes volumes: dbdata: driver: local نضيف حامل الربط إلى خدمة db لملفات تهيئة قاعدة البيانات MySQL التي ننشئها لاحقًا: ... #MySQL Service db: ... volumes: - dbdata:/var/lib/mysql - ./mysql/my.cnf:/etc/mysql/my.cnf ... يربط حامل الربط الملف "‎~/laravel-app/mysql/my.cnf" بالملف "‎/etc/mysql/my.cnf" داخل الحاوية، ومن ثم نضيف حوامل الربط إلى خدمة webserver، إذ توجد خدمتان، تعود الأولى للشيفرة البرمجية للتطبيق والأخرى لتعريف تهيئة خادم Nginx الذي سننشئه في الخطوة 6: #Nginx Service webserver: ... volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network يربط حامل الربط الأول الشيفرة البرمجية للتطبيق في مجلد التطبيق "‎~/laravel-app" بالمجلد "‎/var/www" داخل الحاوية، ويحمّل ملف التهيئة الذي نضيفه إلى المجلد "‎~/laravel-app/nginx/conf.d/‎" إلى المجلد "/etc/nginx/conf.d/" في الحاوية، وبذلك نضيف أو نعدل محتويات مجلد التهيئة حسب الحاجة. نضيف حوامل الربط إلى الخدمة app على النحو التالي: #PHP Service app: ... volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network تربط الخدمة appمجلد التطبيق "laravel-app/~" الذي يحتوي على الشيفرة البرمجية للتطبيق بالمجلد "var/www" في الحاوية لتسريع عملية التطوير، نظرًا لأن أية تغييرات تحصل على مجلد التطبيق المحلي تنعكس على الفور داخل الحاوية. تربط الخدمة أيضًا ملف تهيئة خادم PHP الموجود في المسار "laravel-app/php/local.ini/~" بالملف "usr/local/etc/php/conf.d/local.ini/" داخل الحاوية. يصبح محتوى الملف "docker-compose.yml"على النحو التالي: version: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: digitalocean.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: your_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network #Docker Networks networks: app-network: driver: bridge #Volumes volumes: dbdata: driver: local نحفظ الملف بعد الانتهاء من إجراء التعديلات السابقة. نستطيع الآن باستخدام الأداة دوكر كومبوز بناء الصورة المخصًصة التي أنشأناها لتطبيقنا الخطوة 4- إنشاء ملف Dockerfile يسمح دوكر لك بتخصيص البيئة داخل الحاويات الفردية باستخدام ملف Dockerfile، الذي يمكّننا من إنشاء صور مخصصة يمكننا استخدامها لتثبيت البرنامج الذي يتطلبه التطبيق وضبط الإعدادات بناءً على المتطلبات. يمكن دفع الصور المخصصة التي ننشئها إلى Docker Hub أو أي سجل خاص آخر. نضع الملف Dockerfile ضمن "laravel-app/~"، ولإنشائه ننفّذ الأمر التالي: nano ~/laravel-app/Dockerfile يحدد ملف دوكر هذا الصورة الأساسية ويحدد الأوامر والإرشادات اللازمة لبناء صورة تطبيق لارافيل. نضيف الشيفرة البرمجية التالية إلى الملف: FROM php:7.2-fpm # Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/ # Set working directory WORKDIR /var/www # Install dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ unzip \ git \ curl # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install extensions RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ RUN docker-php-ext-install gd # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Add user for laravel application RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www # Copy existing application directory contents COPY . /var/www # Copy existing application directory permissions COPY --chown=www:www . /var/www # Change current user to www USER www # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"] ينشئ ملف Dockerfile صورةً جديدةً على أساس صورة دوكر php:7.2-fpm المبنية على نظام دبيان Debian، ويثبّت أداة الإدارة PHP-FPM من أجل التحكم بتطبيق PHP FastCGI، كما يثبت حزم لارافيل التالية: mcrypt و pdo_mysql و mbstring و imagick مع composer. يوجه أمر التوجيه RUN الأوامر لتحديث الإعدادات وتثبيتها وتكوينها داخل الحاوية، بما في ذلك إنشاء مستخدم مخصص ومجموعة تسمّى www. تحدد تعليمة WORKDIR المجلد "‎/var/www" على أنه مجلد العمل الأساسي للتطبيق. يخفف إنشاء مستخدم ومجموعة بأذونات مقيدة الخطر الذي ينتج عن الثغرات الأمنية الناتجة عن تشغيل حاويات دوكر. عندما تبدأ الحاوية للعمل فإنها تستخدم حساب الجذر افتراضيًا ما لم يُحدّد مستخدم آخر في ملف الإعداد الخاص بالصورة. يمتلك هذا الحساب الأذونات المطلقة على الجهاز المضيف والحاويات معًا. بدلاً من تشغيل هذه الحاوية باستخدام المستخدم الجذر، ننشئ مستخدمwww يمتلك أذونات القراءة والكتابة على المجلد "var/www/" بفضل تعليمات COPYالتي نستخدمها مع العلامة chown-- لنسخ أذونات مجلد التطبيق. يعرض الأمر EXPOSE المنفذ 9000 في الحاوية لخادم "php-fpm" ويحددCMD الأمر الذي يجب تشغيله بمجرد إنشاء الحاوية، وهو هنا "php-fpm"، الذي سيشغّل الخادم. الخطوة 5- إعداد خادم PHP نُعد خدمة PHP لتعمل مثل معالج PHP للطلبات الواردة من Nginx. ولضبط ذلك ننشئ ملف "local.ini" داخل مجلد "php" الذي ربطناه بالملف "usr/local/etc/php/conf.d/local.ini/" داخل الحاوية في خطوة سابقة، إذ يسمح هذا الملف بتجاوز ملف "php.ini" الافتراضي الذي يفحصه خادم PHP عندما نبدأ بالعمل. ننشئ مجلد php بالأمر التالي: mkdir ~/laravel-app/php نحرر الملف"local.ini" باستخدام محرر النصوص المفضل وبحالة المحرر نانو nano ننفذ الأمر التالي: nano ~/laravel-app/php/local.ini نلصق داخل الملف الأوامر التالية لتحديد أقصى حجم لتحميل الملفات: upload_max_filesize=40M post_max_size=40M تعيّن كل من الخاصتين upload_max_filesize و post_max_size الحجم الأقصى المسموح به لرفع الملفات إلى الخادم، ويوضح تعديل هاتين الخاصتين إمكانية إعداد الملف"php.ini" انطلاقًا من تعديل الملف "local.ini"، ويمكن إضافة أية إعدادات خاصة بخادم PHP نرغب بتطبيقها ضمن هذا الملف. نحفظ الملف بعد إجراء التعديلات السابقة ومن ثم نغلق محرر النصوص، وبهذا ينتهي إعداد خادم PHP وننتقل لإعداد خادم Nginx. الخطوة 6- إعداد خادم Nginx يسمح إعداد خدمة PHP بتعديل خدمة Nginx لاستخدام PHP-FPM مثل خادم FastCGI لتقديم خدمة المحتوى الديناميكي، إذ يعتمد خادم FastCGI على بروتوكول ثنائي binary protocol لربط البرامج التفاعلية بخادم الويب. ننشئ ملف "app.conf" مع ضبط الخدمة في المجلد /laravel-app/nginx/conf.d/~ من أجل إعداد Nginx. ننشئ المجلد "‎/nginx/conf.d" بتنفيذ الأمر التالي: mkdir -p ~/laravel-app/nginx/conf.d ننشئ بعدها الملف "app.conf" بتنفيذ الأمر: nano ~/laravel-app/nginx/conf.d/app.conf نضيف المحتوى التالي لإعداد خادم Nginx: server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; 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 / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } يتضمن إعداد كتلة الخادم الموجهات directives الضرورية لإعداد خادم الويب Nginx إذ تدل هذه الموجهات إلى ما يلي: listen: يحدد هذا الموجه المنفذ الذي يستمع الخادم إليه من أجل استقبال الطلبات. error_log و access_log: تحدد هذه الموجّهات الملفات لكتابة السجلات المتعلقة بالنفاذ للخادم والأخطاء التي تحدث. root: يعيّن هذا الموجه مسار المجلد الجذر root، ويشكّل المسار الكامل لأي ملف مطلوب على نظام الملفات المحلي. يحدد الموجه fastcgi_pass أن الخدمة app تستمع إلى مقبس TCP على المنفذ "9000" وهذا يجعل خادم PHP-FPM يستمع عبر الشبكة بدلاً من مقبس Unix. على الرغم من تفوق مقبس Unix من حيث السرعة بصورةٍ طفيفة على مقبس TCP، إلا أنه لا يحتوي على بروتوكول شبكة وبالتالي يتخطى مكدس الشبكة. يناسب مقبس Unix الحالات التي يتواجد فيها أكثر من مضيف على جهاز واحد، ولكن في الحالات التي يكون لدينا خدمات تعمل على مجموعة موزعة من المضيفات، فيوفّر مقبس TCP ميزة السماح لك بالاتصال بالخدمات الموزعة. نظرًا لأن حاوية التطبيق app الخاصة تعمل على مضيف مختلف من حاوية webserver، يكون مقبس TCP أكثر ملاءمةً للضبط الذي نستخدمه. الخطوة 7- إعداد قاعدة بيانات MYSQL ننشئ ملف "my.cnf" في المجلد "mysql" الذي ربطناه بالملف "‎/etc/mysql/my.cnf" داخل الحاوية بالخطوة 2. يسمح حامل الربط هذا بتجاوز ملف "my.cnf" الأساسي عند الطلب واستخدام الملف الذي نجري التعديلات عليه. نضيف الإعدادات التالية إلى ملف "my.cnf" لتفعيل سجل الاستعلام العام وتحديد ملف السجل. ننشئ أولًا المجلد "mysql" بتنفيذ الأمر التالي: mkdir ~/laravel-app/mysql ومن ثم ننشئ الملف "my.cnf" بتنفيذ الأمر التالي: nano ~/laravel-app/mysql/my.cnf نضيف المحتوى التالي إلى الملف: [mysqld] general_log = 1 general_log_file = /var/lib/mysql/general.log نفعّل سجل الاستعلام بوضع القيمة 1 للخيار general_log ونحدد المكان الذي نريد حفظ السجل به بتحديد قيمة الخيار general_log_file. الخطوة 8- تعديل إعدادات البيئة وتشغيل الحاويات حددنا جميع الخدمات في ملف "docker-compose" وأنشأنا ملفات الضبط لهذه الخدمات وحان الوقت لتشغيل التطبيق. ننشئ نسخةً من الملف "env.example." الذي يولّده لارافيل افتراضيًا ونسمّي النسخة التي نعمل عليها حاليًا "env." بتنفيذ الأمر التالي: cp .env.example .env نعدل على الملف الذي جرى نسخه لنضع البيانات الخاصة بحاوية تطبيقنا باستخدام محرر النصوص المفضل: nano .env نبحث عن الكتلة التي تحدد الاتصال مع قاعدة البيانات DB_CONNECTION ونعدل ضمنها الحقول التالية: DB_HOST: عنوان حاوية قاعدة بيانات db. DB_DATABASE: اسم قاعدة بيانات لارافيل. DB_USERNAME: اسم المستخدم الذي نستخدمه لقاعدة البيانات، نستخدم "laraveluser" ويمكن استخدام أي اسم آخر نرغب به. DB_PASSWORD كلمة المرور للاتصال بقاعدة البيانات. ويكون ملف "env." بالشكل التالي: DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=laraveluser DB_PASSWORD=your_laravel_db_password احفظ التغييرات وأغلق المحرر. ننفذ الآن أمر بدء تشغيل جميع الحاويات وإنشاء وحدات التخزين وإعداد الشبكات وتوصيلها: docker-compose up -d تُحمّل جميع صور دوكر الضرورية عند تشغيل الأمر السابق لأول مرة، وتستغرق بعض الوقت إذا لم تكن موجودة مسبقًا على الجهاز المحلي، وبمجرد تحميل الصور وتخزينها يُنشئ compose الحاويات اللازمة. تضفي الراية d- الطابع الخفي على العملية وتشغّلها في الخلفية. نستعرض الحاويات التي تعمل في هذه اللحظة بتنفيذ الأمر: docker ps يظهر خرجٌ مشابه للخرج التالي ما لم توجد حاويات أخرى إضافية غير "app" و "webserver" و "db" ضمن البيئة: CONTAINER ID NAMES IMAGE STATUS PORTS c31b7b3251e0 db mysql:5.7.22 Up 2 seconds 0.0.0.0:3306->3306/tcp ed5a69704580 app digitalocean.com/php Up 2 seconds 9000/tcp 5ce4ee31d7c0 webserver nginx:alpine Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tc يُعد CONTAINER ID معرفًا فريدًا لكل حاوية ويعرض NAMES اسم الحاوية ويعرض IMAGE اسم الصورة ويوفر الحقل STATUS معلومات حول الحاوية فيما إذا كانت تعمل أو يُعاد تشغيلها أو متوقفة نهائيًا عن العمل. نستخدم الأمر docker-compose exec لتوليد مفتاح التطبيق لتطبيق لارافيل وننسخه للملف "env." ليضمن حماية جلسات المستخدم وتأمين البيانات المشفرة بتنفيذ ما يلي: docker-compose exec app php artisan key:generate نشغّل الأمر التالي: docker-compose exec app php artisan config:cache تُحمّل إعدادات الضبط إلى الملف "‎/var/www/bootstrap/cache/config.php" ضمن الحاوية، وبزيارة الرابط التالي "http://yourserverip" في المتصفح نرى الصفحة التالية: مع تشغيل الحاويات الخاصة بك ومعلومات الضبط في مكانها الصحيح، يمكننا الانتقال إلى تكوين معلومات المستخدم الخاصة بك لقاعدة بيانات "laravel" على حاوية "db". الخطوة 9- إنشاء مستخدم لقاعدة البيانات MySQL يُنشئ MySQL افتراضيًا حساب الجذر root لأغراض إدارية، إذ يتمتع هذا المستخدم بصلاحيات غير محدودة على خادم قاعدة البيانات. نتجنّب استخدام هذا الحساب عند التعامل مع قاعدة البيانات وبدلاً من ذلك ننشئ مستخدم قاعدة بيانات مخصص لقاعدة بيانات تطبيق لارافيل. ننفذ الأمر التالي في حاوية "db": docker-compose exec db bash نسجّل دخول الى حساب الجذر الخاص بقاعدة البيانات MySQL داخل الحاوية: root@c31b7b3251e0:/# mysql -u root -p نُدخل كلمة المرور المُعينة لحساب الجذر الخاص بقاعدة البيانات MySQL أثناء التثبيت في الملف "docker-compose". نتحقق من قاعدة البيانات "laravel" التي حددناها في الملف "docker-compose" بتنفيذ الأمر التالي: mysql> show databases; يظهر خرج يشابه الخرج التالي: +--------------------+ | Database | +--------------------+ | information_schema | | laravel | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) ننشئ حساب المستخدم الذي يُسمح له بالوصول إلى قاعدة البيانات ونسميه "laraveluser". نتأكد من تطابق الاسم وكلمة المرور مع الاسم وكلمة المرور الموجودين في الملف "env.": mysql> GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password'; نمسح الصلاحيات لنُعلم خادم MySQL بالتعديلات التي أجريناها: mysql> FLUSH PRIVILEGES; نخرج من واجهة الأوامر التفاعلية الخاصة بقاعدة البيانات MySQL والحاوية: mysql> EXIT; root@c31b7b3251e0:/# exit الخطوة 10- تهجير البيانات والعمل باستخدام طرفية Tinker نجح إعداد التطبيق إلا أنّ قاعدة البيانات لا تتضمن أية محتوى حتى الآن. نستطيع إدخال بعض المحتوى يدويًا أو الاستفادة من تهجير قواعد البيانات لملئها بمعلومات بصورةٍ سريعة. تُهجّر البيانات باستخدام طرفية tinker، التي تُشغّل الطرفية PsySH عند تحميل تطبيق لارافيل الأولي. تُستخدم الطرفية PsySH مثل واجهة تطوير في وقت التشغيل كما أنها تعمل مثل مصحح أخطاء تفاعلي للغة PHP. تُعد طرفية Tinker بيئة اختبار REPL خاصة لإطار العمل لارافيل. يسمح استخدام الأمر tinker بالتفاعل مع تطبيق لارافيل باستخدام سطر الأوامر في صدفة تفاعلية وتنفيذ الأوامر عليها مباشرةً. نختبر الاتصال بقاعدة البيانات MySQL عن طريق تشغيل أمر artisan migrate، الذي يُنشئ جدول تهجير في قاعدة البيانات داخل الحاوية ويتحقق ذلك بتنفيذ الأمر: docker-compose exec app php artisan migrate ويظهر الخرج الذي يؤكد نجاح التهجير بالشكل التالي: Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table ننفذ الاستعلام التالي للتحقق من وجود اتصال بقاعدة البيانات على نحوٍ صحيح باستخدام الأمر tinker: docker-compose exec app php artisan tinker اختبر اتصال MySQL عن طريق الحصول على البيانات التي هجّرناها للتو: \DB::table('migrations')->get(); يظهر خرج مشابه للخرج التالي مع نجاح العملية: => Illuminate\Support\Collection {#2856 all: [ {#2862 +"id": 1, +"migration": "2014_10_12_000000_create_users_table", +"batch": 1, }, {#2865 +"id": 2, +"migration": "2014_10_12_100000_create_password_resets_table", +"batch": 1, }, ], } تُستخدم tinker للتفاعل مع قواعد البيانات المختلفة وتنفيذ التجارب على النماذج والخدمات المرتبطة بها. الخاتمة أنشأنا في هذا المقال تطبيقًا برمجيًا باستخدام مكدس LEMP يعمل على الخادم المحلي واختبرناه من خلال الوصول إلى صفحة الترحيب في لارافيل وأنشأنا عملية تهجير لقاعدة بيانات MySQL. يمكن استخدام هذه الخطوات العملية في إنشاء تطبيق حقيقي يعتمد على المكونات السابقة. ترجمة وبتصرف للمقال How To Set Up Laravel, Nginx, and MySQL with Docker Compose لصاحبه Faizan Bashir. اقرأ أيضًا تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose كيفية تثبيت Docker Compose على دبيان تنصيب، إعداد واستخدام nginx كخادوم ويب
  14. نستطيع استخدام البوتات الآلية (يُطلق عليها اسم بوتات bots عندما تكون في الويب) لتقديم بيانات مخصصة للمستخدمين بناءً على طلباتهم، إذ يتيح إطارا عمل لارافيل Laravel وبوتمان Potman الأدوات اللازمة لإنشاء بوتات قادرة على تنفيذ هذه المهمة بسهولة. نعمل في هذا المقال على إنشاء بوت تلغرام لمحبي الكلاب باستخدام DOG API، ويمكن اختيار أي نوعٍ مختلفٍ من البيانات عند الرغبة. يظهر البوت عند الانتهاء من العمل كما في الشكل التالي: تثبيت لارافيل وبوتمان يُعد إطار عمل بوتمان مكتبةً خاصةً بلغة البرمجة PHP، وصُمِّمَت لتبسيط عملية تطوير بوتات مبتكرة لمنصات المراسلة المتعددة، مثل منصة سلاك Slack، وتلغرام، وإطار عمل مايكروسوفت بوت وNixmo وفيسبوك وغيرها. $botman->hears('Bot, What’s the best Web Development training website?', function (BotMan $bot) { $bot->reply('DigitalOcean for sure. Give me a harder question!!'); }); تثبيت بوتمان استوديو وفّر المطور مارسيل بوكيوت Marcel Pociot كثيرًا من الوقت على المطورين من خلال تطويره برنامج بوتمان استوديو Botman Studio بالاعتماد على لارافيل مع بوتمان لنحصل على برنامج سهل الاستخدام محدّث باستمرار. ننشئ مشروعًا جديدًا ضمن بوتمان استوديو بتنفيذ التعليمة التالية في موجه الأوامر: composer create-project --prefer-dist botman/studio ilovedogs نتحقق من نجاح عملية التثبيت بتنفيذ التعليمة التالية في موجه الأوامر: php artisan botman:tinker يمكن إدخال الكلمة "Hi" في موجه الأوامر ليظهر الرد بعبارة "Hello" في حالة العمل الصحيح كما هو موضح بالشكل التالي: إنشاء الأوامر يتميز البوت الذي ننشئه بالقدرة على الرد على أنواع مختلفة من الرسائل والأوامر التي تصله، أي أنه يستطيع التعامل مع هذه الحالات: إرسال صورة عشوائية للكلاب من جميع السلالات. إرسال صورة عشوائية للكلب حسب سلالته. إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية. إجراء محادثة وتقديم المساعدة. الاستجابة للأوامر غير المعروفة. لتحقيق هذه الوظائف، نفرغ محتوى الملف "routes/botman.php" لأننا سنضيف له محتوى جديد كليًا ويجب إزالة المحتوى القديم لعدم حصول تعارض. إرسال صورة عشوائية للكلاب من جميع السلالات نحصل على صورة كلب عشوائي من البوت بإرسال الأمر "random/" ونعدل على النص البرمجي في ملف "routes/botman.php" ليصبح كما يلي: <?php use App\Conversations\StartConversation; $botman = resolve('botman'); $botman->hears('/random', 'App\Http\Controllers\AllBreedsController@random'); ننشئ المتحكم باستخدام التعليمة التالية: php artisan make:controller AllBreedsController نكتب الشيفرة البرمجية التالية في المتحكم الذي أنشأناه: <?php namespace App\Http\Controllers; use App\Services\DogService; use App\Http\Controllers\Controller; class AllBreedsController extends Controller { /** * الباني الخاص بالمتحكم * * @return void */ public function __construct() { $this->photos = new DogService; } /** * إعادة صورة عشوائية لكلب من إحدى السلالات * * @return void */ public function random($bot) { // $this->photos->random() يمثل رابط الصورة ‫URL التي تعيدها هذه الخدمة‫‪ // $bot->reply تمثل ما نستخدمه لإرسال الصورة إلى المستخدم $bot->reply($this->photos->random()); } } ننشئ عينةً من الصنف DogService الموجود ضمن الملف "app//services/DogService.php" ليكون مسؤولاً عن الاستجابة لاستدعاءات الواجهة البرمجية API الخاصة بجلب الصور ونضع به الشيفرة البرمجية التالية: <?php namespace App\Services; use Exception; use GuzzleHttp\Client; class DogService { // عنوان الوجهة التي سنحصل منها على صورة الكلاب const RANDOM_ENDPOINT = 'https://dog.ceo/api/breeds/image/random'; /** * Guzzle client. * * @var GuzzleHttp\Client */ protected $client; /** * DogService constructor * * @return void */ public function __construct() { $this->client = new Client; } /** * إحضار وإعادة صورة كلب عشوائية من إحدى السلالات * * @return string */ public function random() { try { // التي استلمناها JSON فك ترميز استجابة $response = json_decode( // التي تعيد الجسم الخاص بالاستجابة API استدعاء $this->client->get(self::RANDOM_ENDPOINT)->getBody() ); // إعادة رابط الصورة return $response->message; } catch (Exception $e) { // نستخدم هذا السطر لإعادة رسالة الخطأ للمستخدم في حال وقوع مشكلة ما. return 'An unexpected error occurred. Please try again later.'; } } } إرسال صورة عشوائية للكلب حسب سلالته نكرر العملية السابقة ولكن نضيف الأمر ‎/b {breed}‎، ونعدل الملف "routes/botman.php" بإضافة السطر البرمجي التالي: botman->hears('/b {breed}', 'App\Http\Controllers\AllBreedsController@byBreed'); نضيف ما يلي على المتحكم AllBreedsController الذي أنشأناه مسبقًا: /** * إعادة صورة كلب من سلالة محددة * * @return void */ public function byBreed($bot, $name) { // نترك أمر معالجة استدعاء الواجهة البرمجية إلى صنف الخدمة ونرد على الطلب القادم بالنتيجة فور وصولها إلينا $bot->reply($this->photos->byBreed($name)); } نضيف التابع byBreed إلى الصنف DogService الذي أنشأناه على النحو التالي: /** * جلب وإعادة صورة عشوائية من سلالة محددة * * @param string $breed * @return string */ public function byBreed($breed) { try { // لدى الطرف الآخر باسم الصنف المحدد %s نستبدل $endpoint = sprintf(self::BREED_ENDPOINT, $breed); $response = json_decode( $this->client->get($endpoint)->getBody() ); return $response->message; } catch (Exception $e) { return "Sorry I couldn\"t get you any photos from $breed. Please try with a different breed."; } } يجب إضافة نقطة النهاية const المُستخدمة أعلاه إلى نفس الملف على النحو التالي: // نقطة النهاية التي سنصل إليها للحصول على صورة عشوائية باسم سلالة معطى const BREED_ENDPOINT = 'https://dog.ceo/api/breed/%s/images/random'; إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية نضيف الأمر ‎/s {breed}:{subBreed}‎ من أجل السلالات الفرعية على النحو التالي: botman->hears('/s {breed}:{subBreed}', 'App\Http\Controllers\SubBreedController@random'); ننشئ متحكمًا جديدًا : php artisan make:controller SubBreedController نعرّف التابع random على النحو التالي: <?php namespace App\Conversations; use App\Services\DogService; use App\Http\Controllers\Controller; class SubBreedController extends Controller { /** * التابع الباني للمتحكم * * @return void */ public function __construct() { $this->photos = new DogService; } /** * إعادة صورة عشوائية لكلب من إحدى السلالات * * @return void */ public function random($bot, $breed, $subBreed) { $bot->reply($this->photos->bySubBreed($breed, $subBreed)); } } يجب إضافة نقطة الاتصال النهائية والتابع الذي حدثنا محتواه إلى الصنف DogService: // تعيد نقطة الاتصال النهائية صورة عشوائية لكلب من سلالة محددة وسلالة فرعية محددة const SUB_BREED_ENDPOINT = 'https://dog.ceo/api/breed/%s/%s/images/random'; /** * جلب وإعادة صورة عشوائية لصورة عشوائية من سلالة معينة وسلالة فرعية * * @param string $breed * @param string $subBreed * @return string */ public function bySubBreed($breed, $subBreed) { try { $endpoint = sprintf(self::SUB_BREED_ENDPOINT, $breed, $subBreed); $response = json_decode( $this->client->get($endpoint)->getBody() ); return $response->message; } catch (Exception $e) { return "Sorry I couldn\"t get you any photos from $breed. Please try with a different breed."; } } إجراء محادثة وتقديم المساعدة لا نحبّذ الرد على كلمات رئيسية مفردة عند برمجة بوت الدردشة، وإنما نجمع معلومات المستخدمين من خلال المحادثة، بحيث يتعامل بوت الدردشة مع كل مستخدم بصورةٍ مناسبة تتوافق مع بياناته. لتحقيق ذلك نضيف الى الملف "routes/botman.php" ما يلي: botman->hears('Start conversation', 'App\Http\Controllers\ConversationController@index'); ننشئ متحكمًا جديدًا: php artisan make:controller ConversationController نعرّف التابع index ضمن الصنف على النحو التالي: <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Conversations\DefaultConversation; class ConversationController extends Controller { /** * إنشاء محادثة جديدة * * @return void */ public function index($bot) { // التي يوفرها إطار العمل بوتمان لبدء محادثة جديدة startConversation نستخدم التابع $bot->startConversation(new DefaultConversation); } } إذا كنا نستخدم بوتمان ستوديو، نجد مجلد باسم "Conversations" ضمن مجلد التطبيق، لذلك ننشئ داخل هذا المجلد ملفًا جديدًا ونسميه "DefaultConversation.php" ونضع فيه المحتوى التالي: <?php namespace App\Conversations; use BotMan\BotMan\Messages\Incoming\Answer; use BotMan\BotMan\Messages\Outgoing\Question; use BotMan\BotMan\Messages\Outgoing\Actions\Button; use BotMan\BotMan\Messages\Conversations\Conversation; class DefaultConversation extends Conversation { /** * بدء المحادثة بالسؤال الاول * * @return void */ public function defaultQuestion() { // نبدأ المحادثة بإضافة السؤال الأول ونضبط الخيارات المتاحة للإجابة على هذا السؤال $question = Question::create('Huh - you woke me up. What do you need?') ->addButtons([ Button::create('Random dog photo')->value('random'), Button::create('A photo by breed')->value('breed'), Button::create('A photo by sub-breed')->value('sub-breed'), ]); // نسأل المستخدم السؤال الذي أعددناه return $this->ask($question, function (Answer $answer) { // نفحص إذا كان المستخدم قد كتب عبارة ما أم ضغط على أحد الخيارات if ($answer->isInteractiveMessageReply()) { // نقارن جواب المستخدم مع الإجابات المعدة مسبقًا switch ($answer->getValue()) { case 'random': $this->say((new App\Services\DogService)->random()); break; case 'breed': $this->askForBreedName(); break; case 'sub-breed': $this->askForSubBreed(); break; } } }); } /** * السؤال عن سلالة الكلب وسلالته الفرعية * * @return void */ public function askForBreedName() { $this->ask('What\'s the breed name?', function (Answer $answer) { $name = $answer->getText(); $this->say((new App\Services\DogService)->byBreed($name)); }); } /** *طلب اسم السلالة وإرسال الصورة * * @return void */ public function askForSubBreed() { $this->ask('What\'s the breed and sub-breed names? ex:hound:afghan', function (Answer $answer) { $answer = explode(':', $answer->getText()); $this->say((new App\Services\DogService)->bySubBreed($answer[0], $answer[1])); }); } /** * بدء المحادثة * * @return void */ public function run() { // يُعد هذه التابع إقلاعي فهو ما سيجري تنفيذه أولًا $this->defaultQuestion(); } } الاستجابة للأوامر غير المعروفة تُستخدم هذه الحالة عندما يرسل المستخدم رسالةً لا يتعرف عليها البوت فلا بد من إعلامه بإعادة طلبه على نحوٍ صحيح. نضيف إلى الملف "routes/botman.php" السطر البرمجي التالي: botman->fallback('App\Http\Controllers\FallbackController@index'); ننشئ متحكمًا جديدًا على النحو التالي: php artisan make:controller FallbackController نضيف الرسالة التي يراها المستخدم عند إرساله لأمر غير معروف: <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; class FallbackController extends Controller { /** * الإجابة برسالة عامة * * @param Botman $bot * @return void */ public function index($bot) { $bot->reply('Sorry, I did not understand these commands. Try: \'Start Conversation\''); } } اختبار البوت إرسال صورة عشوائية للكلاب من جميع السلالات. إرسال صورة عشوائية للكلب حسب سلالته. إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية. إجراء محادثة وتقديم المساعدة. الاستجابة للأوامر غير المعروفة. تثبيت برنامج تشغيل تلغرام بعد الانتهاء من تطوير التطبيق يجب دمجه مع برنامج تلغرام، ولتحقيق ذلك نحتاج برنامج تشغيل التلغرام Telegram driver الذي يقدمه بوتمان والذي نحصل عليه بتنفيذ الأمر: composer require botman/driver-telegram إنشاء بوت تلغرام نفتح تطبيق تلغرام ونبحث عن BotFather ونكتب "‎/newbot" وندخل اسم مستخدم البوت كما في الشكل: نضيف الرمز إلى ملف "env." ونستبدل YOUR_TOKEN بالرمز المميز Token الذي يقدمه تلغرام: TELEGRAM_TOKEN=YOUR_TOKEN تثبيت وتشغيل الأداة ngrok يتطلّب التلغرام استخدام رابط URL صالح وآمن لإعداد الخطافات webhooks وتلقي الرسائل من المستخدمين، ولتحقيق ذلك نستخدم ngrok أو نضع التطبيق على خادم ونُعِد له شهادة SSL، ولكن لسهولة التنفيذ سنستخدم ngrok. نستطيع الحصول عليه من الموقع الرسمي باختيار النسخة المناسبة لنظام التشغيل الذي سنعمل عليه. ننتقل إلى مجلد التطبيق وننفّذ التعليمة: php artisan serve ننتقل إلى المجلد الذي ثبتنا البرنامج ضمنه ونشغل الأداة ngrok بتنفيذ الأمر التالي: /ngrok http 8000 ربط البوت بالتلغرام نربط تطبيقنا ببوت التلغرام الذي أنشأناه مسبقاً بإرسال طلب من نوع POST إلى عنوان الرابط هذا وتمرير عنوان الرابط الذي ولّده ngrok: https://api.telegram.org/bot{TOKEN}/setWebhook نستخدم برنامج بوستمان أو أداة "CURL" لتحقيق ذلك على النحو التالي: curl -X POST -F 'url=https://{YOU_URL}/botman' https://api.telegram.org/bot{TOKEN}/setWebhook يصل الرد التالي بصيغة JSON في حال نجاح العملية: { "ok": true, "result": true, "description": "Webhook was set" } الاختبار باستخدام تلغرام إرسال صورة عشوائية للكلاب من جميع السلالات. إرسال صورة عشوائية للكلب حسب سلالته. إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية. إجراء محادثة وتقديم المساعدة. الاستجابة للأوامر غير المعروفة. الخاتمة قدم هذا المقال طريقةً لتطوير بوت وربطه بإحدى وسائل التواصل الاجتماعي الشهيرة وهي التلغرام، إذ يمكن الاعتماد على إطار العمل بوتمان للربط مع العديد من وسائل التواصل الاجتماعي لتطوير بوت قادر على الاتصال بشريحة واسعة من المستخدمين، كما تضمن المقال خطوات تحديد الأوامر المتاحة للبوت ليتخاطب بها مع المستخدمين وطريقة التعامل مع الحالات الخاصة. ترجمة -وبتصرف- للمقال How To Build a Telegram Bot with Laravel and BotMan لصاحبه Rachid Laasri. اقرأ أيضًا استخدام قوالب Blade لإنشاء عروض Laravel تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder
  15. يُعرّف الاحتواء ضمن حاوية على أنها عملية تكييف التطبيق ومكوناته لتصبح قادرةً على العمل ضمن بيئة بسيطة أساسية المقومات ندعوها الحاوية لتشكّل بيئةً معزولةً يمكن للمستخدم إزالتها بسهولة وسرعة عندما تنتهي حاجته منها أو عندما يرغب بتعديل بعضًا من أجزائها، كما يمكن الاستفادة منها لتطوير واختبار ونشر التطبيقات ضمن بيئات الإنتاج. نعمل في هذا المقال على استخدام الأداة دوكر كومبوز Docker Compose لاحتواء تطبيق لارافيل لتطويره ضمن بيئة مستقلة خاصة به. نحصل على تطبيق لارافيل توضيحي موزّع على ثلاث حاويات خدمة معزولة عن بعضها يعضًا على النحو التالي: خدمة تطبيق "app" تعمل على PHP7.4-FPM. خدمة قاعدة بيانات "db" تحتوي خادم MySQL 5.7. خدمة "nginx" تستخدم خدمة "app" من أجل تحليل شيفرة برمجية بلغة PHP قبل تقديم تطبيق لارافيل للمستخدم النهائي. تُستخدم وحدات التخزين المشتركة Shared Volumes من أجل مزامنة ملفات التطبيق وذلك لتطوير تطبيق بسيط وتصحيح الأخطاء بسهولة؛ كما تُستخدم أوامر docker-compose exec لتشغيل تعليمات Composer و artisan في حاوية التطبيق. المتطلبات الأساسية الوصول إلى حاسب يعمل بنظام التشغيل لينكس أوبنتو Ubuntu ذي رقم إصدار 20.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم، كما يُفضل وجود جدار حماية firewall مثبت ونشط في حال استخدام خادم بعيد. تثبيت الأداة دوكر على الخادم أو الجهاز المحلي. تثبيت الأداة دوكر كومبوز Docker Compose على الخادم أو الجهاز المحلي. الخطوة 1- الحصول على التطبيق التوضيحي نبدأ بتنزيل تطبيق لارافيل التوضيحي من مخزن غيت هب Github وننتقل إلى الفرع tutorial-01، الذي يتضمن تطبيقًا بسيطًا مبنيًا باستخدام لارافيل. نعتمد في هذا العمل على الإصدار tutorial-1.0.1 والذي نحملّه ضمن المجلد الأساسي للمستخدم بتنفيذ الأمر: cd ~ curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip يبدأ تنزيل الملف المضغوط بصيغة "zip" لذلك يجب عند انتهاء التحميل فك الضغط باستخدام الأمر unzip بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا. ننفذ الأمر التالي: sudo apt update sudo apt install unzip ننفذ الأوامر التالي لفك ضغط الملف الذي حملناه ونعيد تسمية المجلد لاسم مناسب لسهولة الوصول إليه: unzip travellist.zip mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo ننتقل إلى المجلّد "travellist-demo" بتنفيذ الأمر: cd travellist-demo الخطوة 2- إعداد ملف الضبط الخاص بالتطبيق نجد عادةً ملفات الضبط الخاصة بلارافيل ضمن المجلد "config" داخل المجلد الجذر للتطبيق. يحتوي الملف "env." معلومات الضبط المتعلقة بالبيئة، مثل بيانات الاعتماد وكلمات المرور وأية معلومات تختلف بين عمليات نشر التطبيقات، لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا. تحذير: يحتوي ملف تهيئة البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب أبدًا مشاركة هذا الملف علنًا. توجد أولويةٌ للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config". تتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات جديدة، مثل إعدادات الاتصال في قاعدة البيانات وخيارات التصحيح ورابط للتطبيق، إضافةً إلى بقية العناصر أو المعلومات التي تختلف تبعًا للبيئة التي يعمل بها التطبيق. ننشئ ملف "env." جديد لضبط خيارات التهيئة لبيئة التطوير التي نُعدها، ويمكننا نسخ الملف "example.env" المتاح افتراضيًا مع أي تطبيق لارافيل بتنفيذ الأمر: cp .env.example .env نحرر الملف باستخدام محرر النصوص نانو nano أو باختيار محرر النصوص المفضّل: nano .env يحتوي ملف "env." الحالي من تطبيق "travellist" التوضيحي على إعدادات لاستخدام التطبيق المُحتَوى المتصل بقاعدة بيانات MySQL محلية أي أنها متاحة على المضيف المحلي "127.0.0.1". نحتاج لتعديل قيمة المتغير DB_HOST لكي يشير إلى قاعدة البيانات التي ننشئها ضمن بيئة دوكر. نعتمد في عملنا على أنّ اسم خدمة قواعد البيانات هو db. نعدّل محتوى الملف لضبط قيم المتغيرات على النحو التالي: APP_NAME=Travellist APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=password ... نستطيع تغيير القيم الخاصة ببقية المتغيرات، مثل اسم قاعدة البيانات وكلمة المرور واسم المستخدم الذين سيُستخدمان عند إعداد الملف "docker-compose.yml" من أجل تهيئة الخدمات. نضغط على الاختصار "CTRL+X" ثم الحرف "Y" وأخيرًا زر الإدخال "Enter" بعد الانتهاء من تعديل الملف. الخطوة 3 - إعداد ملف دوكر الخاص بالتطبيق تستند خدمتا MySQL و Nginx على الصور الافتراضية التي يمكن الحصول عليها من Docker Hub، لكن سنحتاج في مثالنا إلى إنشاء صورة مخصصة لحاوية التطبيق وسننشئ ملف Dockerfile جديد لذلك. تعتمد صورة التطبيق travillist على صورة PHP الرسمية ذات الاسم php:7.4-fpm والمتاحة ضمن مخزن دوكر هب Docker Hub. نحتاج تثبيت بعض حزم PHP الإضافية باستخدام أداة إدارة الاعتمادية Composer. ننشئ مستخدم نظام جديد لتنفيذ الأوامر المختلفة مثل أوامر"Composer" و "artisan" أثناء تطوير التطبيق. يضمن إعداد "uid" امتلاك المستخدم الموجود داخل الحاوية نفس معرف المستخدم الخاص بمستخدم النظام على الجهاز المضيف أثناء تشغيل دوكر. تتزامن الملفات التي تُنشأ من الأوامر في جهاز المضيف باستخدام الأذونات الصحيحة، ونستطيع استخدام أي محرر نصوص لتطوير الشيفرة البرمجية للتطبيق داخل الحاويات. ننشئ ملف Dockerfile جديد بتنفيذ الأمر: nano Dockerfile ننسخ المحتوى التالي إلى ملف Dockerfile: FROM php:7.4-fpm # Arguments defined in docker-compose.yml ARG user ARG uid # Install system dependencies RUN apt-get update && apt-get install -y \ git \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Create system user to run Composer and Artisan Commands RUN useradd -G www-data,root -u $uid -d /home/$user $user RUN mkdir -p /home/$user/.composer && \ chown -R $user:$user /home/$user # Set working directory WORKDIR /var/www USER $user نحفظ الملف بعد الانتهاء من التعديل عليه. يبدأ الملف بتحديد الصورة الأساس التي نستخدمها وهي في حالة الملف السابق php:7.4-fpm. نثبت أداة Composer بنسخ الشكل التنفيذي الخاص بالأمر "composer" والمتاح ضمن أحدث صورة رسمية إلى صورة التطبيق الخاص بنا. ننشئ مستخدم نظام جديد ونبدأ بإعداد المتغيرينuser و uid الذين عرّفناهما في بداية الملف Dockerfile، إذ تُمرَّر هذه المتغيرات إلى الحاوية باستخدام الأداة دوكر كومبوز في وقت البناء. نحدد مسار العمل الافتراضي "var/www/" ونسجّل الدخول بواسطة المستخدم الذي أنشأناه مؤخرًا للتأكد من الاتصال بقاعدة البيانات بصفة مستخدم عادي وأننا في المسار الصحيح عند استخدام الأوامر المختلفة، مثل أوامر"composer" و "artisan" في حاوية التطبيق. الخطوة 4 - إعداد ضبط Nginx وملفات إفراغ قاعدة البيانات يجب مشاركة ملفات الضبط والتهيئة مع حاويات الخدمة عند إنشاء بيئة تطوير باستخدام أداة دوكر كومبوزلإعداد أو التمهيد لهذه الخدمات، إذ يسهّل ذلك إجراء التعديلات على ملفات الضبط وضبط البيئة أثناء تطوير التطبيق. ننشئ مجلد ونضع به الملفات التي تستخدم في تهيئة وبناء حاويات الخدمة. ننشئ مجلد "docker-compose/nginx" ونضع به ملف "travellist.conf" الذي يهيئ آلية تقديم التطبيق وذلك بتنفيذ الأمر التالي: mkdir -p docker-compose/nginx نعدّل محتوى الملف "travellist.conf" باستخدام محرر النصوص المفضل عبر تنفيذ الأمر التالي: nano docker-compose/nginx/travellist.conf نضيف الشيفرة البرمجية التالية داخله: server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; 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 / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } يضبط الملف السابق خادم Nginx ويجبره على الاستماع للمنفذ 80 ويستخدم الصفحة index.php لتكون صفحة الدليل الأساسية للتطبيق. نضبط المسار الجذر Root للمستند ليصبح "‎/var/www/public" ونضبط خادم Nginx ونجبره على استخدام المنفذ "9000" لمعالجة الملفات ذات اللاحقة "php.*". احفظ الملف وأغلقه عند الانتهاء من التعديل. سنشارك من أجل إكمال إعداد قاعدة البيانات MYSQL ملفًا يتضمن محتوى قاعدة البيانات database dump، الذي سيُستورد محتواه إلى قاعدة البيانات عندما نهيئ الحاوية لأول مرة، وتتوفر هذه الميزة في MySQL 5.7 التي نستخدمها في حاوية التطبيق. ننشئ مجلدًا جديدًا لتهيئة ملفات قاعدة البيانات MySQL داخل المجلد "docker-compose" بتنفيذ الأمر التالي: mkdir docker-compose/mysql ننشئ ملف "sql." جديد بتنفيذ الأمر: nano docker-compose/mysql/init_db.sql يعتمد ملف قاعدة البيانات MySQL dump التالي على قاعدة البيانات المُنشأة في دليل لارافيل بالاعتماد على LEMP، إذ يُنشئ جدولًا اسمه places في قاعدة البيانات ثم سيملأ محتوياته بمجموعة من العينات. اكتب الشيفرة البرمجية التالية في الملف "db_init.sql" ليصبح بالشكل التالي: DROP TABLE IF EXISTS `places`; CREATE TABLE `places` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `visited` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0); يتضمن الجدول places ثلاثة حقول id و name و visited وهي على الترتيب معرّف خاص بكل مكان واسم المكان ومتغير يشير إلى زيارة المكان مسبقًا أم لا، ويمكن تعديل أسماء الحقول وإضافة حقول جديدة عند الحاجة. الخطوة 5 - إنشاء بيئة متعددة الحاويات بواسطة دوكر كومبوز تُنشئ الأداة دوكر كومبوز بيئات متعددة الحاويات للتطبيقات التي تعمل على دوكر، كما تستخدم تعريفات الخدمة لبناء بيئات قابلة للتخصيص بالكامل مع حاويات متعددة يمكنها مشاركة الشبكات وأحجام البيانات، مما يتيح التكامل السلس بين مكونات التطبيق المختلفة. ننشئ ملفًا جديدًا يسمى "docker-compose.yml"، والذي يمكن أن يكون موجودًا مسبقًا في مجلد الجذر للتطبيق، إذ يحدد هذا الملف بيئة الحاويات بما في ذلك الصور الأساسية لبناء التطبيق وكيفية تفاعل الخدمات ضمنه. نحدد ثلاث خدمات مختلفة ضمن ملف "docker-compose.yml"، هي: "app" و "db" و "nginx"؛ إذ تُنشئ خدمة "app" صورةً تسمى "travellist" بناءً على ملف Dockerfile الذي أنشأناه سابقًا، وتُشغّل الحاوية التي تحددها هذه الخدمة خادم "php-fpm" لتحليل شيفرات PHP وتُرسل النتائج مرةً أخرى إلى خدمة "nginx، التي تعمل على حاوية منفصلة. تحدد خدمة "mysql" حاويةً تُشغل خادم MySQL 5.7. تتصل هذه الخدمات فيما بينها باستخدام شبكة جسر أسميناها "travellist". تُزامن ملفات التطبيق على كل من الخدمتين "app" و "nginx" عبر حوامل الربط، التي تُعد مفيدةً في بيئات التطوير لأنها تتيح مزامنةً ثنائية الاتجاه بين الجهاز المضيف والحاويات. نُنشئ ملفًا جديدًا باسم "docker-compose.yml" في مجلد الجذر للتطبيق بتنفيذ الأمر: nano docker-compose.yml يبدأ ملف "docker-compose.yml" التقليدي برقم الإصدار يليها تعريف الخدمات "services" الخاصة بالتطبيق، كما تُعرَّف الشبكات التي يشاركها التطبيق في نهاية الملف. إذًا، يكون محتوى هذا الملف كما يلي: version: "3.7" services: networks: travellist: driver: bridge سنعدّل الآن عقدة "services" لتتضمن خدمات "app" و "db" و "nginx". خدمة التطبيق app تُعِد خدمة "app" حاويةً باسم "travellist-app" وتبني صورة دوكر جديدة بناءً على Dockerfile الموجود في نفس مسار الملف "docker-compose.yml" وتُحفظ الصورة محليًا باسم "travellist". نحتاج تواجد ملفات التطبيق ضمن حاوية التطبيق "app" حتى ولو كانت هذه الملفات موجودةً في جذر المستند الذي جرى تقديمه على أنه تطبيق موجود في حاوية "nginx"، ونحتاج ذلك من أجل تنفيذ أوامر "artisan" الخاصة بإطار عمل لارافيل على هذه الملفات. نضيف البيانات التالية إلى الملف "docker-compose.yml": app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist تحقق هذه الإعدادات ما يلي: build: يعلِم هذا الضبط أداة دوكر كومبوز ببناء صورة محلية لخدمة التطبيق، باستخدام المسار المحدد context وملف Dockerfile للحصول على التعليمات. تُحقن المتغيرات user و uid في ملف Dockerfile لتخصيص أوامر إنشاء المستخدم في وقت الإنشاء. image: تُعدّ الاسم الذي يستخدم الصورة قيد الإنشاء. container_name: تُعِدّ اسم الحاوية لهذه الخدمة. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقافٌ الخدمة. working_dir: يعيّن المجلّد الافتراضي لهذه الخدمة، مثل "‎/var/www". volumes: يُنشئ وحدة تخزين مشتركة تُزامِن المحتويات من المسار الحالي إلى "‎/var/www" داخل الحاوية، ويبقى موجودًا في حاوية "nginx". networks: تُعِدّ هذه الخدمة لاستخدام شبكة باسم "travellist". خدمة قاعدة البيانات db تستخدم خدمة "db" صورة MySQL 5.7 من مخزن دوكر هب. تحمّل الأداة دوكر كومبوز الملفات المتغيرة "env." الموجودة في نفس المسار الذي يحتوي الملف "docker-compose.yml"، ونحصل على إعدادات قاعدة البيانات ملف "env." الذي قد ولّدناه عند إنشاء تطبيق لارافيل. نضع البيانات التالية بعد البيانات التي وضعناها للخدمة "app": db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: تحدد صورة دوكر التي ستستخدم في هذه الحاوية. نستخدم صورة MySQL 5.7 من دوكر هب Docker Hub. container_name: اسم الحاوية travellist-db. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف للخدمة. environment: تُحدد متغيرات البيئة في الحاوية الجديدة. نستخدم القيم التي حصلنا عليها من ملف "env." لإعداد خدمة قاعدة البيانات MySQL والتي تنشئ تلقائيًا قاعدة بيانات ومستخدمًا جديدًا بناءً على متغيرات البيئة المتوفرة. volumes: ينشئ وحدة تخزين لتهيئة قاعدة بيانات التطبيق. تستورد صورة MySQL ملفات"sql." تلقائيًا والتي توجد في المسار ‎/docker-entrypoint-initdb.d داخل الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. الخدمة nginx تستخدم خدمة "nginx" صورة Nginx مبنية مسبقًا على توزيعة لينكس اسمها Alpine. تنشئ حاوية باسم "travellist-nginx" وتُعيد التوجيه من المنفذ "8000" الى المنفذ "80" داخل الحاوية. نضع البيانات التالية بعد بيانات خدمة "db": nginx: image: nginx:1.17-alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: اسم صورة دوكر التي تستخدم في هذه الحاوية وهي في هذه الحالة الصورة Alpine Nginx 1.17 . container_name: اسم الحاوية travellist-nginx. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقافٌ للخدمة. ports: تعيد توجيه المنفذ الذي يسمح بالوصول الخارجي عبر المنفذ 8000 إلى خادم الويب الذي يعمل على المنفذ 80 داخل الحاوية. volumes: تنشئ وحدتي تخزين مشتركتين، بحيث تزامن الوحدة الأولى المحتويات من نقطة العمل إلى المسار ‎/var/www داخل الحاوية ويفيد ذلك بنقل التعديلات المحلية إلى التطبيق الذي يقدّمه Nginx تلقائيًا. تنسخ الوحدة الثانية ملفات الإعداد الخاصة بخدمة nginx الموجودة في الملف "docker-compose/nginx/travellist.conf" الى ملفات الإعداد الخاصة بخدمة nginx ضمن الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. وعليه يصبح ملف "docker-compose.yml" على الشكل التالي: version: "3.7" services: app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist nginx: image: nginx:alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d/ networks: - travellist networks: travellist: driver: bridge نتأكد من حفظ الملف بعد الانتهاء من إجراء التعديلات السابقة. الخطوة 6 - تشغيل التطبيق عبر أداة دوكر كومبوز ننشئ صورة تطبيق جديد ونشغّل الخدمات التي حددناها ضمن الإعدادات باستخدام الأمر التالي: docker-compose build app يستغرق الأمر بضعة دقائق، ثم يظهر الخرج التالي: Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest نُشغّل البيئة بالخلفية بعد الانتهاء من مرحلة الإنشاء بتنفيذ الأمر: docker-compose up -d ويكون الخرج على النحو التالي: Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done نستعرض معلومات حالة الخدمة النشطة حاليًا بتنفيذ الأمر: docker-compose ps ويكون الخرج على النحو التالي: Name Command State Ports -------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:8000->80/tcp أصبحت البيئة الآن جاهزة للعمل، ولكن يجب تنفيذ بعض الأوامر قبل انتهاء إعداد التطبيق كاملًا. نستخدم الأمر docker-compose exec لتنفيذ جميع الأوامر ضمن الحاويات، فلو رغبنا بتنفيذ الأمر ls –l الذي يظهر معلومات مفصلة حول الملفات في مسار التطبيق، ننفذ الأمر التالي: docker-compose exec app ls -l وسيكون خرج شبيهًا بالخرج التالي: total 260 -rw-rw-r-- 1 sammy sammy 737 Jun 9 11:19 Dockerfile -rw-rw-r-- 1 sammy sammy 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy sammy 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy sammy 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy sammy 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy sammy 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy sammy 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy sammy 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy sammy 4096 Jun 9 11:19 docker-compose -rw-rw-r-- 1 sammy sammy 965 Jun 9 11:27 docker-compose.yml -rw-rw-r-- 1 sammy sammy 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy sammy 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy sammy 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy sammy 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy sammy 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy sammy 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy sammy 4096 Jan 7 08:05 tests drwxrwxr-x 41 sammy sammy 4096 Jun 9 11:32 vendor -rw-rw-r-- 1 sammy sammy 538 Jan 7 08:05 webpack.mix.js نشغّل الأداة composer install لتثبيت اعتماديات التطبيق كما يلي: docker-compose exec app composer install يظهر الخرج التالي بعد إتمام العملية: Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. يجب أن نولد مفتاح التطبيق الفريد باستخدام الأداة artisan الخاصة بلارافيل قبل أن نختبر التطبيق الذي طورناه، إذ يشفّر هذا المفتاح جلسات المستخدم والبيانات الحساسة الأخرى. ننفذ الأمر التالي: docker-compose exec app php artisan key:generate ويكون الخرج على النحو التالي: Application key set successfully. نطلب الرابط التالي من المتصفح: http://server_domain_or_IP:8000 ملاحظة: نطلب العنوان المحلي "http://localhost:8000" في حالة العمل على حاسب محلي ضمن المتصفح لتشغيل التطبيق التوضيحي الذي نطوّره. يظهر عندها الخرج التالي: نستطيع استخدام الأمر logs لفحص السجلات التي تولّدها الخدمة بتنفيذ الأمر التالي: docker-compose logs nginx Attaching to travellist-nginx … travellist-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh travellist-nginx | /docker-entrypoint.sh: Configuration complete; ready for start up travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:34 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:35 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" … نستطيع إيقاف العمل مؤقتًا لبيئة دوكر كومبوز مع الحفاظ على حالة الخدمات بتشغيل الأمر: docker-compose pause ليكون الخرج على النحو التالي: Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done نستطيع استئناف العمل بتنفيذ الأمر: docker-compose unpause ويكون الخرج على النحو التالي: Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done نستطيع إيقاف عمل بيئة دوكر كومبوز ونزيل جميع حاوياتها وشبكاتها ووحدات تخزينها بتنفيذ الأمر التالي: docker-compose down ويكون الخرج على النحو التالي: Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist الخاتمة أعددنا بيئة دوكر بثلاث حاويات باستخدام أداة دوكر كومبوز Docker Compose وحددنا بنيته الأساسية في ملف YAML. يمكن العمل على تطبيق لارافيل Laravel دون الحاجة إلى تثبيت خادم ويب محلي وإعداده للتطوير والاختبار، ويتحقق كل ذلك باستخدام بيئة معزولة يمكن تكرارها وإعادة إنشائها بسهولة حتى الوصول إلى التطبيق المطلوب تثبيته ضمن بيئات الإنتاج. ترجمة وبتصرف للمقال How To Install and Set Up Laravel with Docker Compose on Ubuntu 20.04 لصاحبه Erika Heidi. اقرأ أيضًا مدخل إلى دوكر Docker نشر تطبيقات Laravel على منصة Heroku تثبيت Laravel 5 وإعداده على Windows وUbuntu
×
×
  • أضف...