نشر تطبيقات Rails بواسطة Git Hooks على أوبونتو 14.04


محمد بغات

في هذا الدرس، ستتعلم كيفية استخدام خُطّافات (Git (Git hooks لأتمتة نشر بيئة الإنتاج لتطبيقات Rails على خادم أوبونتو 14.04 عن بُعد. باستخدام خُطّافات Git ستتمكن من نشر التطبيقات عن طريق دفع التغييرات إلى خادم الإنتاج production server، وبدلًا من أن تقوم بكل شيء يدويًّا (مثل ترحيل قاعدة البيانات) فالاستعانة بأحد أشكال النشر الآلي، مثل خُطّافات Git، سيوفر عليك الكثير من الوقت على المدى الطويل.
في هذا الدرس سنستخدم خُطّافGit من نوعpost-receive ، بالإضافة إلىPuma كخادم للتطبيق،Nginx كوكيل عكسي لـ Puma و PostgreSQL كقاعدة بيانات.

المتطلبات الأساسية

سوف تحتاج صلاحيات مستخدم غير جذري non-root والذي يملك امتيازات مستخدم أساسي superuser على خادم أوبونتو. في هذا المثال، سيكون اسم المستخدم deploy. يمكنك تعلم كيفية فعل ذلك في هذا الدرس: الإعداد الابتدائي لخادوم أوبنتو 14.04. إذا كنت ترغب في النشر دون الحاجة لإدخال كلمة المرور، فتأكد من إعداد مفاتيح SSH.
سوف تحتاج إلى تثبيت Ruby على خادمك. إذا لم تكن قد فعلت ذلك سلفًا، يمكنك تثبيته جنبًا إلى جنب مع Rails باستخدام rbenv أو RVM.
سوف تحتاج أيضًا إلى تطبيق Rails مُدار في مستودع git على جهازك. إذا لم يكن لديك تطبيق في git، فسوف نقدم لك تطبيقًا بسيطًا كمثال لتعمل عليه.
لنبدأ على بركة الله.

تثبيت PostgreSQL

معظم بيئات Rails تستخدم PostgreSQL كقاعدة بيانات، لذلك عليك تثبيته على خادمك الآن.
على خادم الإنتاج، قم بتحديث apt-get:

sudo apt-get update

ثم قم بتثبيت PostgreSQL بهذه التعليمات:

sudo apt-get install postgresql postgresql-contrib libpq-dev
Quote

ملاحظة: عليك أيضًا تثبيت PostgreSQL على جهاز التطوير خاصتك، حتى تتمكن من تثبيت مكتبة pg (مُحوّل PostgreSQL) محلّيا. سيكون هذا ضروريًا لتشغيل bundle install عندما نضيف المكتبة لملف Gemfile الخاص بتطبيقك. تختلف خطوات التثبيت من نظام تشغيل لآخر، لذلك سيكون عليك القيام ببعض البحث والتجريب.

إنشاء قاعدة بيانات الإنتاج الخاصة بالمستخدم

لإبقاء الأمور بسيطةً، سنسمي قاعدة بيانات الإنتاج الخاصة بالمستخدم بنفس اسم التطبيق خاصتك. على سبيل المثال، إذا كان اسم تطبيقك “appname”، فيجب عليك إنشاء مستخدم PostgreSQL بهذه الطريقة:

sudo -u postgres createuser -s appname

لتعيين كلمة مرور لقاعدة بيانات المستخدم، ادخُل سطر أوامر PostgreSQL هكذا:

sudo -u postgres psql

بعد ذلك قم بتعيين كلمة المرور لقاعدة بيانات المستخدم “appname” هكذا:

\password appname

قم بإدخال كلمة المرور التي تريد ثم قم بتأكيدها.
اخرج من سطر أوامر PostgreSQL بهذه التعليمة:

\q

الآن نحن على استعداد لتزويد تطبيقك بمعلومات الاتصال الخاصة بقاعدة البيانات.

إعداد تطبيق Rails

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

اختياري: إنشاء تطبيق Rails

إن كان لديك تطبيق Rails جاهز للنشر. فيمكنك تخطي هذا القسم والقيام بالتغييرات المناسبة لاحقًا. أمّا إن لم يكن لديك تطبيق جاهز، فإن الخطوة الأولى هي إنشاء تطبيق Rails جديدة.
هذه التعليمات ستنشئ تطبيق Rails جديد تحت اسم “appname” في المجلد الرئيسي. لا تتردد في استبدال “appname” بالاسم الذي تريد:

cd ~
rails new appname

ثم تحوّل إلى مجلد التطبيق:

cd appname

لأجل تطبيقنا هذا، سوف نقوم بتوليد سقالة scaffold controller لكي يجد تطبيقنا شيءً ليعرضه:

rails generate scaffold Task title:string note:text

لنتأكدْ الآن من أن تطبيقنا موجود في مستودعgit .

تهيئة Git Repo

إن لم يكن تطبيقك موجودًا بالفعل في مستودع git لسبب ما، قم بتهيئته وإجراء إلزام أولي initial commit.
قم بالتحوّل إلى مجلد التطبيق. في مثالنا، التطبيق يسمى " appname" وهو موضوع في المجلد الرئيسي home directory:

cd ~/appname
git init
git add -A
git commit -m 'initial commit'

الآن دعونا نُجهّز تطبيقنا لربط الاتصال بقاعدة بيانات الإنتاج لـ PostgreSQL.

تحديث إعدادات قاعدة البيانات

تحوّل إلى مجلد تطبيقك إن لم تكن بالفعل هناك. في مثالنا، التطبيق يسمى “appname” وهو موضوع في المجلد الرئيسي home directory:

cd ~/appname

الآن افتح ملف إعداد قاعدة البيانات في محرر النصوص المفضل لديك:

vi config/database.yml

اعثر على مقطع الإنتاج production section في إعدادات قاعدة بيانات تطبيقك، وقم باستبداله بمعلومات الاتصال بقاعدة بيانات الإنتاج خاصتك. من المفروض أن يبدو كشيء من هذا القبيل (قم باستبدال القيم عند الاقتضاء):

config/database.yml excerpt

production:
  <<: *default
  host: localhost
  adapter: postgresql
  encoding: utf8
  database: appname_production
  pool: 5
  username: <%= ENV['APPNAME_DATABASE_USER'] %>
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>

احفظ واخرج.
هذا الملف يؤكد على أن بيئة الإنتاج الخاصة بالتطبيق ينبغي أن تستخدم قاعدة بيانات PostgreSQL تحت مُسمّى “appname_production” على المضيف المحلي localhost. لاحظ أنه تم إحالة اسم المستخدم وكلمة مرور قاعدة البيانات إلى متغيرات البيئة environment variables. سنقوم بتحديدها على الخادم في وقت لاحق.

تحديث Gemfile

إذا لم يكن لدى Gemfile خاصتك المكتبة pg (PostgreSQL adapter gem)، ولم تكن المكتبة Puma مُحددة، فيجب عليك إضافتهما الآن.
افتح Gemfile الخاص بتطبيقك في المحرّر المفضل لديك:

vi Gemfile

أضف الأسطر التالية إلىGemfile :

Gemfile excerpt

group :production do
  gem 'pg'
  gem 'puma'
end

احفظ واخرج. سيحدد هذا النص البرمجي أن بيئة الإنتاج production environment يجب أن تستخدم المكتبات pgوpuma :

إعداد Puma

قبل إعداد Puma، يجب عليك أن تتحقق من عدد وحدات المعالجة المركزية التي يملكها خادمك. يمكنك بسهولة فعل ذلك على خادمك بهذه التعليمة:

grep -c processor /proc/cpuinfo

الآن، على جهاز التطوير خاصتك، قم بإضافة إعدادات Puma إلى الإعداد config/puma.rb . افتح الملف في محرر النصوص:

vi config/puma.rb

انسخ وألصق هذه الإعدادات في الملف:

config/puma.rb

# Change to match your CPU core count
workers 2

# Min and Max threads per worker
threads 1, 6

app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"

# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"

# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

on_worker_boot do
  require "active_record"
  ActiveRecord::Base.connection.disconnect! rescue Ac-tiveRecord::ConnectionNotEstablished
  Ac-tiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end

قم بتغيير العددworkers إلى عدد وحدات المعالجة المركزية لخادمك. يفترض المثال أن لديك اثنان.
احفظ واخرج. الآن تم إعداد Puma بموضعlocation تطبيقك وموضع مقبسه socket والمذكرات logs ومعرّفات العمليات PIDS. لا تتردد في تعديل الملف، أو إضافة الخيارات التي تناسبك.
ألزمCommit التغييرات الأخيرة:

git add -A
git commit -m 'added pg and puma'

قبل الاستمرار، قم بتوليد المفتاح السري والذي سيتم استخدامه لبيئة الإنتاج الخاصة بتطبيقك:

rake secret
rake secret sample output:
29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89

سوف تنسخ المُخرجات وتستخدمها لتحديد القيمة SECRET_KEY_BASE الخاصة بتطبيقك في الخطوة التالية.

إنشاء النص البرمجي لإطلاق Puma

سنقوم بإنشاء نص برمجي للإطلاق (Upstart init script). حتى نتمكن من تشغيل وإيقاف Puma بسهولة، وللتأكد من أنه سيبدأ عند بدء التشغيل.
على خادم الإنتاج خاصتك، حمّل أداة Jungle Upstart من مستودع Puma على GitHub وضعها في المجلد الرئيسي:

cd ~
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
	
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf

الآن افتح الملف puma.conf حتى تتمكن من تحرير إعدادات النشر الخاصة بمستخدمPuma :

vi puma.conf

ابحث عن السطرين الذين يحددان setuid و setgid، و قم باستبدال “apps” باسم النشر الخاص بالمستخدم أو المجموعة خاصتك. على سبيل المثال، إذا كان اسم مستخدم النشر “deploy”، فينبغي أن تكون الأسطر هكذا:

puma.conf excerpt 1 of 2

setuid deploy
setgid deploy

الآن ابحث عن السطر الذي يحتوي:exec /bin/bash <<'EOT'. أضف الأسطر التالية تحته، وتأكد من استبدال اسم المستخدم وكلمة المرور الخاصة ب PostgreSQL، وأضف كذلك rake secret الذي قمت بإنشائه سابقًا:

puma.conf excerpt 2 of 2

  export APPNAME_DATABASE_USER='appname'
  export APPNAME_DATABASE_PASSWORD='appname_password'
  export SECRET_KEY_BASE='rake_secret_generated_above'

احفظ واخرج.
الآن انسخ النصوص في مجلد خدمات الإطلاق Upstart services:

sudo cp puma.conf puma-manager.conf /etc/init

النص البرمجي puma-manager.conf يُحدد /etc/puma.conf كمرجع لمعرفة التطبيقات التي يجب إدارتها. دعونا ننشئ ونحرّر هذا الملف الآن:

sudo vi /etc/puma.conf

كل أسطر هذا الملف يجب أن تتضمن مسارات التطبيقات التي تريد من Puma أن يُديرها. سنقوم بنشر تطبيقنا في مجلد يُسمى “appname” داخل المجلد الرئيسي. في هذا المثال، سيكون كما يلي (تأكد من تعديل المسار ليتناسب مع المكان الذي يتواجد فيه تطبيقك):

/etc/puma.conf

/home/deploy/appname

احفظ واخرج
الآن تمّ إعداد تطبيقك لينطلق عند بدء التشغيل بمساعدة Upstart, وهذا يعني أن تطبيقك سيبدأ حتى بعد إعادة إقلاع خادمك. لا تنسى أننا لم ننشر التطبيق حتى الآن، لذلك لسنا جاهزين لتشغيله بعد.

تثبيت وإعداد Nginx

لجعل التطبيق متاحًا على شبكة الإنترنت، يجب أن تستخدم Nginx كخادم.
قم بتثبيت Nginx باستخدام apt-get:

sudo apt-get install nginx

الآن افتح كتلة الخادم الافتراضي default server block بمحرر النصوص:

sudo vi /etc/nginx/sites-available/default

استبدل محتويات الملف بالتعليمات البرمجية التالية. تأكد من استبدال الأجزاء الملوّنة باسم المستخدم واسم التطبيق المناسبين.

/etc/nginx/sites-available/default

upstream app {
    # Path to Puma SOCK file, as defined previously
    server unix:/home/deploy/appname/shared/sockets/puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name localhost;

    root /home/deploy/appname/public;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

احفظ واخرج. سيقوم هذا النص البرمجي بإعداد Nginx كوكيل عكسي، لذلك طلبات HTTP ستُرسل إلى الخادم Puma عبر مقبس يونيكس Unix socket. لا تتردد في إجراء التغييرات التي تراها مناسبةً.
لن نقوم بإعادة تشغيل Nginx, فالتطبيق غير موجود بعدُ على الخادم.
سنقوم بإعداد التطبيق فيما يلي.

إعداد مستودع الإنتاج (git (Prepare Production Git Remote

على خادم الإنتاج، قم بتثبيت git بواسطة apt-get:

sudo apt-get install git

ثم قم بإنشاء مجلد للمستودع البعيد remote repository. سنقوم بإنشاء مجلد git أوّلي في المجلد الرئيسي وسنسميه “appname_production”. يمكنك تسمية المستودع البعيد كما تريد (ولكن لا تضعه في ~/appnameلأنه المكان الذي سننشر فيه التطبيق):

mkdir ~/appname_production
cd ~/appname_production
git init –bare

بما أن هذا المستودع أوّلي، فلا يوجد مجلّد عمل بعدُ وجميع الملفات الموجودة في .git موجودة في المجلد الرئيسي نفسه.
نحن بحاجة إلى إنشاء خُطّاف git من نوعpost-receive ، والذي هو النص البرمجي الذي سيتم تشغيله عندما يتلقى خادم الإنتاج دفعةً من git(git push). افتح الملف hooks/post-receive في محرر النصوص:

vi hooks/post-receive

انسخ وألصق النص التالي في الملف post-receive:

hooks/post-receive

#!/bin/bash

GIT_DIR=/home/deploy/appname_production
WORK_TREE=/home/deploy/appname
export APPNAME_DATABASE_USER='appname'
export APPNAME_DATABASE_PASSWORD='appname_password'

export RAILS_ENV=production
. ~/.bash_profile

while read oldrev newrev ref
do
    if [[ $ref =~ .*/master$ ]];
    then
        echo "Master ref received.  Deploying master branch to produc-tion..."
        mkdir -p $WORK_TREE
        git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
        mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log

        # start deploy tasks
        cd $WORK_TREE
        bundle install
        rake db:create
        rake db:migrate
        rake assets:precompile
        sudo restart puma-manager
        sudo service nginx restart
        # end deploy tasks
        echo "Git hooks deploy complete"
    else
        echo "Ref $ref successfully received.  Doing nothing: only the mas-ter branch may be deployed on this server."
    fi
done

تأكد من تحديث القيم التالية:

  • GIT_DIR :مجلد المستودع الأولي لـ (git (bare git repository الذي قمت بإنشائه في وقت سابق
  • WORK_TREE : المجلد حيث تريد نشر تطبيقك (يجب أن يتطابق مع الموضع الذي قمت بتحديده في إعدادات Puma)
  • APPNAME_DATABASE_USER :اسم مستخدم PostgreSQL (ضروري لمهام rake )
  • APPNAME_DATABASE_PASSWORD : كلمة مرور PostgreSQL (ضروري لمهام rake )

بعد ذلك، يجب عليك مراجعة التعليمات الموجودة بين التعليقين # start deploy tasks و # end deploy tasks. هذه هي التعليمات التي سيتم تشغيلها في كل مرة يتم دفع push الشعبة الرئيسية master branch إلى مستودع الإنتاج في(git (appname_production. إذا تركتها كما هي، فسيحاول الخادم القيام بما يلي بالنسبة لبيئة الإنتاج الخاصة بتطبيقك:

  • تشغيل المُحزّم bundler
  • إنشاء قاعدة بيانات
  • ترحيل قاعدة البيانات
  • الترجمة الأوليةPrecompile للأصول assets
  • إعادة تشغيل Puma
  • إعادة تشغيل Nginx

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

chmod +x hooks/post-receive

Sudo بلا كلمة مرور Passwordless Sudo

لأن الخُطّاف post-receive يحتاج إلى تشغيل تعليماتsudo ، فسنسمح للمستخدم deploy باستخدام sudo بدون كلمة مرور(استبدل اسم المستخدمdeploy في حال اخترت اسمًا مختلفًا):

sudo sh -c 'echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'

هذا سيسمح للمستخدم deploy بتشغيل التعليمة sudo دون الحاجة لإعطاء كلمة المرور. ربما تريد أن تُقيّد التعليمات التي يمكن للمستخدمdeploy القيام بها. وكحد أدنى، عليك استخدام مفتاح المصادقة SSH كما عليك تعطيل المصادقة بكلمة المرور password authentication.

إضافة Production Git Remote

الآن بعد أن أعددنا كل شيء لخادم الإنتاج، دعونا نضيف production git remote لمستودع التطبيق خاصتنا.
على جهاز التطوير خاصتك، تأكد من أنك في مجلد التطبيق:

cd ~/appname

ثم قم بإضافة مستودع git بعيد (git remote) جديد تحت اسم “production” والذي يشير إلى مستودع git الأولي appname_production الذي أنشأته على خادم الإنتاج. استبدل اسم المستخدم (deploy) وعنوان الـ IP الخاص بالخادم واسم المستودع البعيد (appname_production):

git remote add production deploy@production_server_public_IP:appname_production

لقد صار تطبيقك الآن جاهزًا للنشر بواسطة git push.

النشر للإنتاج Deploy to Production

بعد كل الإعدادات التي قمنا بها، يمكنك الآن نشر تطبيقك على الخادم خاصتك عن طريق تشغيل تعليمات git التالية:

git push production master

هذا سيدفع push شعبتك الرئيسية المحلية local master branch إلى مستودع الإنتاج البعيد production remote الذي قمت بإنشائه سابقًا. عندما يتلقى production remote أمر الدفع، فسينفّذ النصَّ البرمجي post-receive الذي أعددناه في وقت سابق. إذا قمت بكل شيء بشكل صحيح، فيجب أن يكون تطبيقك متاحًا الآن على عنوان الـ IP العام لخادم الإنتاج خاصتك.
إذا كنت تستخدم التطبيق التعليمي لهذا الدرس، فمن المفروض أن تكون قادرًا على الوصول إلى http://production_server_IP/tasks من أيّ متصفح و من المفروض أن ترى شيئًا من هذا القبيل:

01.png

الخلاصة

في أي وقت تقوم بإجراء تغيير على تطبيقك، يمكنك تشغيل نفس التعليمة git push للنشر على خادم الإنتاج خاصتك. هذا لوحده من المفروض أن يوفر عليك الكثير من الوقت على مدى عمر المشروع.
لقد شمل هذا الدرس فقط الخطّافات من نوع “post-receive”، ولكن هناك عدة أنواع أخرى من الخطّافات التي يمكن أن تساعدك على تحسين أتمتة عملية النشر.

ترجمة -وبتصرّف- للمقال How To Deploy a Rails App with Git Hooks on Ubuntu 14.04 لصاحبه Mitchell Anicas





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن