هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في أول أجزاء عن الخطوات الأساسيّة من أجل نشر تطبيق، وهي تشكل نقطة بداية من أجل الخطوات المذكورة في هذا الدّرس.
سنغطّي في هذا الدّرس إعداد قاعدة البيانات (بما في ذلك كلمة السّر)، هدفنا في النهاية هو الحصول على خادوم يعمل عليه تطبيق PHP بشكل كامل مع الإعدادات المذكورة آنفًا.
سنستخدم إطار عمل Laravel كمثال عن تطبيق PHP ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك.
الخطوة الأولى – تثبيت حزم MySQL
سنقوم في هذه الخطوة بإعداد قاعدة بيانات MySQL لكي يستخدمها تطبيقنا.
إنّ الخطوة الأولى لضمان وجود MySQL مُثبّتة على خادومنا هي ببساطة إضافة الحِزَم المطلوبة إلى مهمّة تثبيت الحِزَم في أعلى الـ playbook لدينا، الحزم التي نحتاجها هي mysql-server
، mysql-client
، وphp5-mysql
، سنحتاج أيضًا إلى python-mysqldb
كي تستطيع Ansible التواصل مع MySQL.
وبما أنّنا نضيف حِزَم فنحتاج إلى إعادة تشغيل nginx
و php5-fpm
لضمان قابلية استخدام الحِزَم الجديدة من قبل التطبيق، نحتاج في هذه الحالة أن تكون MySQL متوفرة من أجل PHP لكي تستطيع الاتصال إلى قاعدة البيانات.
من الأشياء الرائعة حول Ansible هي أنّنا نستطيع تعديل أي مهمّة من المهام وإعادة تشغيل الـ playbook وسيتم حينها تطبيق التغييرات، يتضمّن هذا قوائم من الخيارات كما نملك مع مهمّة apt
.
نفتح الملف php.yml
من أجل تحريره:
nano php.yml
نبحث عن المهمّة install packages
ونحدّثها لتضم الحِزَم السابقة:
Updated php.yml . . . - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - mysql-server - mysql-client - php5-mysql - python-mysqldb notify: - restart php5-fpm - restart nginx . . .
نقوم بحفظ وتشغيل الـ playbook:
ansible-playbook php.yml --ask-sudo-pass
الخطوة الثانية – إعداد قاعدة بيانات MySQL
سنقوم في هذه الخطوة بإنشاء قاعدة بيانات MySQL من أجل تطبيقنا.
تستطيع Ansible التخاطب مباشرة مع MySQL باستخدام الوحدات المسبوقة بـ mysql_
(مثل mysql_db
، mysql_user
)، تزودنا الوحدة mysql_db
بطريقة لضمان وجود قاعدة بيانات ذات اسم مُحدّد بحيث نستطيع استخدام مهمّة مثل هذه لإنشاء قاعدة البيانات:
New Ansible task - name: Create MySQL DB mysql_db: name=laravel state=present
نحتاج أيضًا إلى حساب مستخدم صحيح مع كلمة سر معروفة للسماح لتطبيقنا بالاتصال إلى قاعدة البيانات، إحدى الوسائل لتحقيق هذا هي توليد كلمة السر محليًّا وحفظها في playbook الخاصّة بـ Ansible، ولكنّ هذه الطريقة غير آمنة وتوجد وسيلة أفضل منها.
سنقوم بتوليد كلمة السّر باستخدام Ansible على الخادوم ذاته واستخدامها مباشرة عند الحاجة، ولتوليد كلمة سر سنستخدم أداة الأوامر السطرية makepasswd
ونطلب منها كلمة سر مكوّنة من 32 حرف، ولأنّ makepasswd
لا تأتي بشكل افتراضي مع Ubuntu سنحتاج إلى إضافتها إلى قائمة الحِزَم أيضًا.
سنخبر أيضًا Ansible أن تتذكر خَرْج output هذا الأمر (أي تتذكر كلمة السّر) حتى نستطيع استخدامها لاحقًا في الـ playbook الخاصّة بنا، ومع ذلك ولأنّ Ansible لا تعلم إذا ما كان قد تم تنفيذ الأمر shell
فسنقوم بإنشاء ملف عند تنفيذ هذا الأمر، ستتحقّق Ansible من وجود الملف وإن وجدته فستفترض أنّه تمّ تشغيل ذلك الأمر ولن يتم تشغيله مرّة أخرى.
تبدو المهمّة كما يلي:
New Ansible task - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/laravel/.dbpw register: dbpwd
نحتاج بعدها لإنشاء مستخدم قاعدة بيانات MySQL الفعلي مع كلمة السّر التي حدّدناها، يتم عمل ذلك باستخدام الوحدة mysql_user
ونستطيع استخدام الخيار stdout
على المتغيّر الذي عرّفناه خلال مهمّة توليد كلمة السّر للحصول على الخَرْج الخام لأمر الصدفة shell، مثل هذا: dbpwd.stdout
.
يقبل الأمر mysql_user
اسم المستخدم والصلاحيّات المطلوبة، نريد في حالتنا إنشاء مستخدم يُدعى laravel
وإعطاء هذا المستخدم صلاحيّات كاملة على الجدول laravel
، نحتاج أيضًا إلى إخبار المهمّة أن يتم تشغيلها فقط عندما يتم تغيير المتغيّر dbpwd
، والذي سيحدث فقط عند تشغيل مهمّة توليد كلمة السّر.
يجب أن تبدو المهمّة كما يلي:
New Ansible task - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed
وبوضع كل ذلك معًا نفتح الملف php.yml
من أجل تحريره كي نستطيع إضافة المهمّة السابقة:
nano php.yml
نبحث في البداية عن المهمّة install packages
ونقوم بتحديثها لتتضمّن الحزمة makepasswd
:
Updated php.yml . . . - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - mysql-server - mysql-client - php5-mysql - python-mysqldb - makepasswd notify: - restart php5-fpm - restart nginx . . .
نضيف بعدها مهام توليد كلمة السّر، إنشاء قاعدة بيانات MySQL، وإنشاء مستخدم في نهاية الملف:
Updated php.yml . . . - name: UFW limit <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr> ufw: rule=limit port=<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> - name: UFW open HTTP ufw: rule=allow port=http - name: Create MySQL DB mysql_db: name=laravel state=present - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/laravel/.dbpw register: dbpwd - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed handlers: . . .
لا تقم بتشغيل الـ playbook الآن، ربّما تكون قد لاحظت أنّه بالرغم من أنّنا أنشأنا مستخدم وقاعدة بيانات MySQL فلم نفعل أي شيء مع كلمة السّر، سنغطّي هذا الموضوع في الخطوة القادمة، عند استخدام مهام shell
ضمن Ansible فمن المهم دومًا أن نتذكّر متابعة سير العمل الذي يتعلّق بخَرْج ونتائج المهمّة بأكمله قبل تشغيلها لنتجنّب الاضطرار إلى تسجيل الدخول يدويًّا وإعادة تعيين الحالة.
الخطوة الثالثة – إعداد تطبيق PHP من أجل قاعدة البيانات
سنقوم في هذه الخطوة بحفظ كلمة سر قاعدة بيانات MySQL في الملف .env
من أجل التطبيق.
سنحدّث الملف .env
ليتضمن اعتمادات (credentials) قاعدة بياناتنا التي أنشأناها حديثًا، يحتوي ملف .env
الخاص بـ Laravel الأسطر التالية بشكل افتراضي:
Laravel .env file DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret
نستطيع الإبقاء على السطر DB_HOST
كما هو، ولكن سنحدّث الأسطر الثلاثة الأخرى باستخدام المهام التالية، وهي مشابهة جدًّا للمهام التي استخدمناها في الدّرس السابق من أجل تعيين APP_ENV
و APP_DEBUG
:
New Ansible tasks - name: set DB_DATABASE lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel - name: set DB_USERNAME lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel - name: set DB_PASSWORD lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed
وكما فعلنا مع مهمّة إنشاء مستخدم MySQL فقد استخدمنا متغيّر كلمة السر التي تمّ توليدها (dbpwd.stdout
) لنشر الملف مع كلمة السّر، وأضفنا الخيار when
لضمان أن يتم تشغيلها فقط عند تغيير dbpwd
.
وبما أنّ الملف .env
موجود مسبقًا قبل إضافة مهمّة توليد كلمة السّر، فسنحتاج إلى حفظ كلمة السّر إلى ملف آخر، تبحث مهمّة توليد كلمة السّر عن وجود الملف (والذي أعددناه مسبقًا ضمن المهمّة)، سنستخدم أيضًا الخيارات sudo
وsudo_user
لإخبار Ansible أن يقوم بإنشاء الملف عن طريق المستخدم www-data
:
New Ansible task - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed
نفتح الملف php.yml
من أجل تحريره:
nano php.yml
نضيف المهام السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي:
Updated php.yml . . . - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed - name: set DB_DATABASE lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel - name: set DB_USERNAME lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel - name: set DB_PASSWORD lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed handlers: . . .
لا تقم بتشغيل الـ playbook الآن، فقد بقيت لدينا خطوة واحدة يجب إكمالها قبل أن نتمكّن من تشغيل الـ playbook.
الخطوة الرابعة – تهجير قاعدة البيانات Migrating the Database
سنقوم في هذه الخطوة بتنفيذ تهجير قاعدة البيانات database migrations من أجل إعداد جداول قاعدة البيانات.
يتم فعل هذا في Laravel عن طريق تنفيذ الأمر migrate
(على سبيل المثال php artisan migrate --force
) بداخل دليل Laravel، لاحظ أنّنا أضفنا العَلَم force--
لأنّ بيئة production
تحتاجه.
تبدو مهمّة Ansible للقيام بهذا كما يلي:
New Ansible task - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed
حان الوقت الآن لتحديث playbook الخاصّة بنا، نفتح الملف php.yml
لتحريره:
nano php.yml
نضيف المهام السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي:
Updated php.yml . . . - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed handlers: . . .
بإمكاننا أخيرًا حفظ وتشغيل الـ playbook:
ansible-playbook php.yml --ask-sudo-pass
عند الانتهاء من تنفيذ هذا نقوم بتحديث الصفحة في متصفحنا ويجب أن نرى عندها رسالة تقول:
your_server_ip/'>http://your_server_ip/ Queue: NO Cron: NO
يعني هذا أنّ تم إعداد قاعدة البيانات بشكل صحيح وأنّها تعمل كما هو متوقع، ولكنّنا لم نقم حتى الآن بإعداد مهام cron أو عفريت الطابور queue daemon، والتي سنقوم بها في الدرس القادم.
الخاتمة
تحدّثنا في هذا الدّرس عن طريقة إعداد قاعدة بيانات MySQL وإعداد تطبيق PHP من أجلها ومن ثمّ تهجير قاعدة البيانات من أجل نشر تطبيق PHP متقدّم باستخدام Ansible.
ترجمة -وبتصرّف- لـ How To Deploy an Advanced PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.