Источник, спасибо автору.
Идея
Идея Ruby Version Manager состоит в разработке, где требуется иметь
одновременно несколько версий Ruby и различные варианты Rails под ними.
Общая схема:
Представляет собой стандартную схему frontend + backend. В качестве backend выступает nginx с модулем passenger
- nginx (frontend) - проксирование, стандарт;
- nginx (backend's) - работа приложений через passenger:
- каждый backend работает на порту 8<Ruby-version> (например, 8191, 8192);
- каждое приложение, работая под версией Ruby, может использовать требуемый Rails (через gemset).
Сервер на котором производилась установка: Debian 5.0.8 i686.
Установка
Устанавливаем пакеты необходимые для компиляции:
apt-get install git-core git curl file \
gcc make automake autoconf automake1.9 \
binutils g++ g++-multilib checkinstall
apt-get install libssl-dev libxslt-dev libxml2-dev
apt-get install libcurl4-openssl-dev libmysql++-dev
apt-get install libpcre3 libpcre3-dev
RVM
Установка RVM:
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
/etc/rvmrc
umask g+w
export rvm_path="/usr/local/rvm"
export rvm_source_path="${rvm_path}/src"
export rvm_log_path="${rvm_path}/log"
export rvm_bin_path="${rvm_path}/bin"
export rvm_gems_path="$rvm_path/gems"
export rvm_tmp_path="${rvm_tmp_path:-"$rvm_path/tmp"}"
export rvm_install_on_use_flag=0
export rvm_gemset_create_on_use_flag=0
# export rvm_make_flags="-j7"
export rvm_trust_rvmrcs_flag=1
export rvm_pretty_print_flag=1
~/.bashrc
if [ -s "$HOME/.rvm/scripts/rvm" ]; then
source "$HOME/.rvm/scripts/rvm" # This loads RVM into a shell session.
elif [ -s "/usr/local/rvm/scripts/rvm" ]; then
source "/usr/local/rvm/scripts/rvm"
fi
Ruby в RVM
Установка Ruby:
rvm package install zlib
rvm install 1.9.1-p378 --with-zlib-dir=$rvm_path/usr
rvm install 1.9.2-p180 --with-zlib-dir=$rvm_path/usr
Проверка выбора Ruby
# rvm --default use 1.9.1
# rvm list
rvm rubies
=> ruby-1.9.1-p378 [ i386 ]
ruby-1.9.2-p180 [ i386 ]
Системный Passenger
Сборка и установка passenger:
cd /usr/local/src
wget http://rubyforge.org/frs/download.php/74471/passenger-3.0.5.tar.gz
tar -xzvf ./passenger-3.0.5.tar.gz
mv -f passenger-3.0.5 /usr/local/
Passenger установлен в /usr/local/passenger-3.0.5
Поддержка SSL в Ruby
Добавление поддержки SSL:
rvm gem install rack
rvm package install openssl
rvm use ruby-1.9.1-p378
cd /usr/local/rvm/src/ruby-1.9.1-p378/ext/openssl/
ruby extconf.rb
make
make install
rvm use ruby-1.9.2-p180
cd /usr/local/rvm/src/ruby-1.9.2-p180/ext/openssl/
ruby extconf.rb
make
make install
Сборка backend (nginx + passenger-module)
Собираем nginx с модулем passenger. Исходники помещаем в /usr/local/src :
cd /usr/src
wget http://sysoev.ru/nginx/nginx-1.0.2.tar.gz
tar xzvf nginx-1.0.2.tar.gz
Далее необходимо скачать и развернуть исходники
pcre-8.10
cd /usr/local/src/nginx-1.0.2
Сконфигурировать сборку:
sh ./configure \
--prefix='/usr/local/nginx' \
--with-http_ssl_module \
--with-pcre='/usr/local/src/pcre-8.10' \
--add-module='/usr/local/passenger-3.0.5/ext/nginx' \
--user=www-data \
--group=www-data \
--error-log-path=/var/log/nginx-rb/error.log \
--pid-path=/var/run/nginx-rb.pid \
--lock-path=/var/lock/nginx-rb.lock \
--http-client-body-temp-path=/var/lib/nginx-rb/body \
--http-proxy-temp-path=/var/lib/nginx-rb/proxy \
--http-fastcgi-temp-path=/var/lib/nginx-rb/fastcgi \
--with-http_ssl_module \
--with-http_dav_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--without-mail_pop3_module \
--without-mail_smtp_module \
--without-mail_imap_module
В результате подготовлена сборка nginx-ruby-backend в каталог /usr/local/nginx
Выполнить сборку debian-пакета:
checkinstall -D make install
Указать имя пакета "nginx-rb" и описание пакета "Nginx-1.0.2 (backend) with passenger-3.0.5 module"
Настройка
frontend
Стандартная настройка. Варианты проксирования:
- по количеству backends/приложений;
- "универсально" - в зависимости от $request_uri/$server_name переводить на тот или иной upstream.
Второй вариант потребует меньше конфигураций и изменений во frontend.
backend
На примере backend ruby-1.9.2.
Настроим для запуска дополнительный экземпляр nginx-backend:
/usr/local/nginx/etc/nginx-rb-192.conf:
Узнать путь к конфигурационному файлу nginx-rb-192.conf (pass-to-ruby):
# rvm use ruby-1.9.2-p180 && which ruby
/etc/init.d/nginx-rb-192:
Включить в автозапуск:
# update-rc.d nginx-rb-192 defaults
Passenger
В конфигурации виртуального хоста backend необходимо указать (минимально):
server {
listen 8192;
server_name <app_name>.domain.tld;
root /home/applications/<app_name>/prod/bin/public;
rails_env production;
passenger_user <app_name_user>;
passenger_group <app_name_user>;
passenger_enabled on;
}
Ruby
Gemsets
Принципиально возможно использовать несколько версий Rails под каждой
развернутой Ruby. Достигается это манипуляциями с RVM/Gemset.
Пример. Для Ruby-1.9.2 необходимо иметь rails-2.3.5 и rails-3.0.5
Формируем 2 gemset'а:
# rvm ruby-1.9.2-p180
# rvm gemset create rails235 rails305
ERROR: Gemset 'rails305' does not exist, rvm gemset create 'rails305' first.
'rails235' gemset created (/usr/local/rvm/gems/ruby-1.9.2-p180@rails235).
'rails305' gemset created (/usr/local/rvm/gems/ruby-1.9.2-p180@rails305).
Ошибка в выводе не принципиальна, появляется не всегда.
В итоге под ruby-1.9.2 имеется 3 gemset'а:
- global - набор по-умолчанию (gem'ы из него автоматически доступны из всех наборов)
- rails235
- rails305
В дальнейшем возможны следующий манипуляции:
- в global устанавливать gem'ы, необходимые для базовой поддержки приложений (не требующие вариаций по версиям и т.п.);
- в railsNNN - устанавливать непосредственно rails требуемой версии и связанные с ним gem'ы.
Возможно более разветвленное дерево gemset'ов (в данной статье не рассматривается).
Установка gem в gemset (важен выбор назначения — ruby-<version>@<gemset>):
# rvm 1.9.2-p180@rails305
# gem install rails -v 2.3.5
# rvm 1.9.2-p180@rails306
# gem install rails -v 3.0.5
Информация по выбранному gemset'у:
# rvm gemset list
gemsets for ruby-1.9.2-p180 (found in /usr/local/rvm/gems/ruby-1.9.2-p180)
global
rails235
=> rails305
Приложения
Для использования возможностей RVM необходимо выдержать следующую схему размещения приложений:
Структура каталогов:
/home/applications/<app_name>/<app_type> - корневой каталог
(app_root) - домашний каталог пользователя-владельца приложений;
/home/applications/<app_name>/<app_type>/bin - каталог приложения (app_home)
В каталогах создать (dot)rvmrc — файлы:
- для app_root (непосредственно позволяет использовать RVM):
rvm_path="/usr/local/rvm"
rvm_trust_rvmrcs_flag=1
rvm_install_on_use_flag=1
- для app_home (позволяет автоматически выбирать при входе в этот каталог версию Ruby и, при необходимости, gemset под RVM):
#!/usr/bin/env bash
environment_id="ruby-1.9.2-p180@rails305"
if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] ; then
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
[[ -s ".rvm/hooks/after_use" ]] && . ".rvm/hooks/after_use"
else
rvm --create use "$environment_id"
fi
Собственно выбор версии - environment_id.
В app_home, в configure/ поместить файл setup_load_paths.rb:
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
begin
rvm_path = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
rvm_lib_path = File.join(rvm_path, 'lib')
$LOAD_PATH.unshift rvm_lib_path
require 'rvm'
RVM.use_from_path! File.dirname(File.dirname(__FILE__))
rescue LoadError
# RVM is unavailable at this point.
raise "RVM ruby lib is currently unavailable."
end
end
# Select the correct item for which you use below.
# If you're not using bundler, remove it completely.
# If we're using a Bundler 1.0 beta
ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
require 'bundler/setup'
# Or Bundler 0.9...
if File.exist?(".bundle/environment.rb")
require '.bundle/environment'
else
require 'rubygems'
require 'bundler'
Bundler.setup
end
Контроль
Nginx
Штатные методы, с учетом наличия нескольких экземпляров.
Ruby
Вывод текущей версии Ruby:
# rvm list
Вывод текущего gemset:
# rvm gemset list
Вывод списка установленных gem:
# rvm gem list
Rails
Для перезапуска rails-процесса достаточно сделать в каталоге приложения:
# touch tmp/restart.txt
Passenger
Проверка статуса passenger:
-
/usr/local/passenger-3.0.5/bin/passenger-status
Выдает несколько PID (по количеству backends);
-
/usr/local/passenger-3.0.5/bin/passenger-status <PID>
Выдает статус rails-процессов по выбранному backend.
Ограничения
GEM могут быть установлены только от привилегированного пользователя.
Для установки gem от имени непривилегированного пользователя требуется
доработка.
Литература
- Phusion Passenger users guide, Nginx version
- NGINX
- Using RVM rubies with Passenger