ازاي ترفع مواقع اللارفيل باحترافية على السرفر باستخدام Bitbcket
في الرحلة دي هكون الدليل بتاعك لازاي تقدر ترفع مواقع اللارفيل بتاعتك على اكتر من سيرفر بالستخدام CI و Pipeline اللي هيخلي حياتك سهلة وسلسه وكمان هيرفع الموقع بدون ماحد يحس وبدون مايقع ولا ثانية.
البوست دا تيكنيكال ومفصل جدا وفيه اكواد كتير ولكن على قد ماقدرت حاولت استحدام كلمات بسيطة لوصف المصطلحات المعقدة, ومع ذلك اي كود هتنسخو هيشتغل على طول!
# خريطة الرحلة
# قبل ما نبدأ
في السكشن دا:
# تأكد ان عندك SSH للسيرفر
في الاول, لازم يكون عندك ssh للسيرفر اللي هترفع عليه cd
ادخل على الفلدر الرئيسي او المكان اللي عاوز ترفع عليه على السرفر في الغالب هيكون في المسار ده /home/example.com/public_html/
واعمل فولدر اسمو "production".
cd /home/example.com/public_html
mkdir production
# اعمل bitbucket repo
الخطوة دي اختيارية اذا المشروع بتاعك بالفعل على bitbucket ممكن تعدي الخطوة دي للي بعدها.
اعمل برانش سميه master
او production
اللي تشوفو واللي يناسبك, اي بوش هتطلع على البرانش دا هتفعل عملية رفع و هتستخدم متغيرات البئية اللي هنعملها سوى في السكشن اللي جاي.
# ظبط اعدادات الريبو و بيئة الرفع
في ال bitbucket روح ل Repository settings
وبعدين ل Repository variables
هنا هتلاقي كل المفاتيح او الاعدادات السرية اللي اكيد مش هتعوز انها تكون مكشوفة في حته عامة.
ضيف DEPLOY_HOST
و DEPLOY_USER
في المتغيرات الاتنين دولا هيشيلو ال ip بتاع السرفر و اليوزر اللي هيعمل عملية الرفع عليه.
انتبه! خلي بالك ماتخليش ال DEPLOY_USER يكون root, ده مش مستحسن خالص, خلي المستخدم اللي هيعمل عملية الرفع يكون محدود واخرو يأكسس الفولدر بتاع الرفع فقط.
بعد كدا هنظبط اعدادات بيئة الرفع سواءا كانت production او staging في ال Deployments
هتخش وهتضيف DEPLOY_PATH
اللي هتشيل مسار الرفع لحد فولدر ال production.
بعد كدا هتخلي ال bitbucket pipeline يأكسس السرفر بتاعك بالستخدام اليوزر بتاع الرفع هتدخل على تاب ال SSH Keys
وهتعمل generate new key اذا ماعملتش كدا قبل كدا, بعدها هتنسخ ال publick key
لملف ال .ssh/authorized_keys
على السرفر ولكن خلي بالك انك تنسخو على الملف بتاع اليوزر بتاع الرفع في الغالب المسار هيكون /home/example/.ssh
.
خلي بالك من الخطأ دا, ماتنسخش ال public key لل .ssh بتاع ال root user كدا ال bitbucket هيكون عندو صلاحيات الروت تأكد انك تنسخو على اليوزر بتاع الرفع.
اذا لأي سبب من الاسباب فولدر ال .ssh
ماكنش موجود تقدر تضيفو بسهولة من خلال الامر التالي:
ssh-keygen -t rsa
بعد ما تنفذ الامر دا هيقلك Enter file in which to save the key (/home/example/.ssh/id_rsa):
تأكد من مسار الملف كويس.
- اختياريا تقدر تتأكد من ان ال pipeline يقدر يدخل على السرفر بالضغط على زرار
Fetch
اللي هيعرف ال bitbucket على ال ip بتاع السرفر.
# انشاء ملف bitbucket-pipeline.yaml
بعد كدا خش على مجلد المشروع بتاعك واعمل ملف اسمو bitbucket-pipeline.yaml
الوقتي حاول تنسخ محتويات الملف من هنا (opens new window) ولو عاوز تعرف شرح الملف دا كمل قراءة هتعرف 😃
الملف اللي لسه ناسخو دا فيه بيئات رفع مختلفة Deployment Enviroments هما staging
و production
لو حابب تقدر تضيف او تحذف في البيئات دي بعد ما تقرا السكشن دا كويس!
# انشاء ملف Envoy.blade.php
هتعمل ملف اسمو Envoy.blade.php
في مجلد المشروع بتاعك وتاني حاول برضو تنسخ محتويات الملف من هنا (opens new window) وبعدين بص على الشرح بعد ما نخلص مش لازم تعمل اي حاجة فيه الوقتي. لو حابب تعرف محتوايته حالا ممكن تنط للسكشن دا من هنا.
# اخطأ هتسهرك هتحيرك
انا قعد ساعات طويلة في الخطأ دا, سرفر الاباتشي ماكنش قادر يقرأ ملف ال storage
لما بحدث فيه وكان بيظهرلي المجلد القديم ال cached ودا كلو لان ال symoblic link او الرابط بتاع المجلد اللي اسمو current
في مجلد ال production
ماكنش الاباتشي ماشي معاه بمعنا انه كان بيظهر النسخة المتكيشة مش المجلد الفعلي, المهم بعد 25 كباية قهوة عرفت الخطأ انه نسيت احط السطر دا في ملف ال .htaccess
في المجلد الاساسي بتاع الرفع public_html
.
Options +FollowSymLinks
السطر دا هيخلي سرفر الاباتشي يحمل الملفات اللي جوا ال symoblic link صح.
# ازاي كل حاجة مترابطة ببعضها؟
خلينا ناخد خطوة لورا ونبص على ازاي كل حاجة بتشتغل ومترابطة ببعضها وعلى انهي سيرفر الاوامر هتتنفذ.
# نظرة عامة عن خطوات تنفيذ الاوامر
1- لما تعمل push لاي كود جديد على البرانش بتاعك ال pipeline هيشغل عملية رفع جديدة اللي متعرفة في ملف ال bitbucket-pipeline.yaml
.
2- ال pipeline هيقوم دوكر كونتينر حاجة زي سيرفر منعزل مخصوص للرفعة دي عشان يبني فيها ال php هيعمل فيها composer install والناتج عن العملية دي هتكون ملفات المشروع بتاعك + ملف ال vendor
.
3- بعد كدا ال Task runner اسمو Envoy (opens new window) هيشغل كل الاوامر والخطوات اللي جوا الملف Envoy.blade.php
على ال pipeline وعلى السرفر بتاعك.
# شرح محتويات مجلد البرودكشن
خلينا نلقي نظرة على هيكلة المجلدات جوا مجلد ال production
على السرفر.
releases
يحتوي على اصدار من كل push متعلمة بالتاريخ..env
ملف .env العادي بتاع البرودكشن بس الملف دا هيكون متشير مابين كل الاصدارات.storage
مجلد ال storage العادي بس هيكون برضو متشير مابين كل الاصدارات.
# السرفرات المتعرفه جوا Envoy.blade.php
Envoy.blade.php
بيعرف 2 سرفر هما:
web
اللي بيمثل السرفر بتاعك.localhost
اللي بيمثل الكونتينر بتاعت pipeline على bitbucket.
# خلينا نعرف الاسكربتات جوا ال Envoy
# Rsync
- اول خطوة هتشتغل على
localhost
. بينقل او بيحول ملفات المشروع كلو واي نواتج مثل مجلد ال vendor من سيرفر bitbucket للسرفر او للمجلد بتاعك اللي متعرف فيDEPLOY_PATH
.
# Setup Symlinks
- بيربط
.env
اللي موجود في مجلدproduction
بأحدث اصدار موجود في مجلد الreleases
. - بيشوف لو الاصدار فيه مجلد ال
storage
, بينقلو لمجلد backup وبعدها بياخد symlink لل احدث اصدار موجود في الreleases
. - بيربط ال
storage
بpublic/storage
. زي اللي بيعملوphp artisan storage:link
.
# Verify Install
"verify_install", هنا تقدر تضيف اي اوامر عشان تتأكد من ان الاصدار دا شغال انا هنا عملت حاجة بسيطة artisan --version
.
# Activate Releases
"activate_release", عمل symlink ل ملف ال current
مع اجدد اصدار في مجلد ال releases
.
مهم جدا لازم تظبط السرفر بتاعك سواءا كان Nginx او Apache انو يقرأ الدومين بتاعك من ملف ال current يعني في الاخر هيكون المسار كدا path-to-production-dir/production/current/public
# Migration
"migrate", اعمل اي حاجة ليها علاقة بالداتابيس او migration هنا لازم تستخدم فلاج --force
عشان انت في البرودكشن لو ماستخدمتوش التاسك مش هتشتغل.
# Optimizations
"optimize", هنا او حبيت تعمل اي optimizations للاصدار بتاعك.
نصيحة: استخدم امر php artisan optimize:clear
عشان تنضف كل الكاشات بتاعتك وبعدها امر php artisan optimize
عشان تكيش كل حاجة تاني.
# Additional tasks
"additional_tasks", هنا لو حابب تعمل اي تاسكات اضافية زي انك تنشر الترجمات او ال views.
# قوة ال Symlink
لو حظك حلو ومشيت كل الخطوات من هنا ورايح كل push لل master اللي انا بفترض انك بتستخدمو ك production هيترفع على السرفر كأصدار جديد, السحر هنا بقا ان ملف ال current
دائما بيبص على اخر اصدار شغل من الكود بتاعك ولما بتpush اي كود جديد ال current
هيبص على الاصدار الجديد دا في ثانية بدون اي تأخير وبكدا هتكون حققت ال zero downtime deployment. الحلو في الموضوع برضو ان كل الاصدارت القديمة هتكون محفوظة على السرفر يعني لا قدر الله حتى لو الاصدار عدى من كل شيئ وطلع بايظ تقدر ترجع ورا للاصدار القديم اللي كان شغال. ايه رايك يا معلم!
# bitbucket-pipeline.yaml
الملف دا بيحتوي على خطوات هتشتغل على pipeline زي نوع الدوكر او اصدار ال php, البرانشات اوالاسكربتات وحجات تانية كتير.
خلينا نبص عليه بصة سريعة:
image: php:7.4-fpm
انا بالنسبالي كان مهم ان الpipeline يكون سريع جدا يعني مايخدش اكتر من دقيقتين عشان كدا انا هنا استخدمت صورة دوكر مخصوصة للphp النسخة دي فيها بيئة محدودة ومختصرة عشان تشغل اللphp باسرع وقت ممكن طبعا انت مش ملزم بنفس النسخة دي وتقدر تجرب نسخ كتير جدا من على موقع docker.
steps:
- step: &composer-install
name: Build PHP
caches:
- composer
script:
- ls -al
- apt-get update && apt-get install -qy unzip git curl libmcrypt-dev
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- composer --version
- composer install --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --optimize-autoloader --prefer-dist --ignore-platform-reqs
artifacts:
- vendor/**
definitions
بيعرف اي خطوات او متغيرات هتشتغل خلال فترة تفيذ ال pipeline run.
او حاجة عرفت ال composer install
- هتنزل الcomposer على الimage
- هتطبع اصدار الcomposer
- هتحمل ال vendor بس optimized
- هتكيش ال vendor عشان المرات الجاية يستخدمو ومايضطرش يحملو تاني.
مهم جدا انك composer install
عشان الvendor اللي هيطلع هيشتغل على البرودكشن ولازم يكون سريع وحجمو صغير.
- step: &deploy-production
name: Deploy (Production)
deployment: Production
caches:
- composer
script:
- apt-get update && apt-get install -qy unzip git curl libmcrypt-dev rsync
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- composer --version
- composer global require "laravel/envoy"
- ~/.composer/vendor/bin/envoy run deploy --host=$DEPLOY_HOST --user=$DEPLOY_USER --path=$DEPLOY_PATH --build=$BITBUCKET_BUILD_NUMBER --commit=$BITBUCKET_COMMIT --branch=$BITBUCKET_BRANCH --php=php --dir=$BITBUCKET_CLONE_DIR
هنا الpipeline هينزل ال "rsync" و ال "Laravel Envoy (opens new window)" على ال pipeline ويشغل ال Envoy
pipelines:
default:
- step: *composer-install
# - step: *npm-build
branches:
master:
- step: *composer-install
# - step: *npm-build
- step: *deploy-production
جوا ال pipelines
هنعرف الاوامر اللي هتحصل في كل branch.
# كلمات اخيرة
مش لازم تستخدم ال Bitbucket بعينو اي منصة فيها pipeline هتقدر تنفذ عليها الطريقة دي اهم شيء تكون فاهم الفكرة منصات زي Travis Ci او Github actions هيشتغلو زي الفل طالما ال pipeline له ssh على السرفر عشان يقدر يشغل الوامر بتاعت ال Envoy (opens new window).
لو عندك اي سؤال او تعليق او عاوز تسلم عليا ممكن تسيب تعليق تحت او تتواصل معايا عن طريق تويتر @nagiworks (opens new window) هكون سعيد جدا بمساعدتك.