
Хочу поделиться с вами способом разворачивания нескольких приложений Ruby on Rails на одном сервере.
Поможет нам в этом RVM, Unicorn и Nginx.
Недавно заказчик попросил поставить Redmine к ним на сервер, на котором уже крутился проект на Ruby on Rails и использующий версию руби 1.9.2. А redmine работает максимум с ruby-1.8.7. Так как других проектов на сервер размещать не предполагалось, то там изначально поставили Nginx + mod_passenger. Как известно, используя mod_passenger на одном сервере не запустишь два приложения с разными версиями руби.
Для начала установим для каждого проекта свое окружение при помощи RVM.
Предполагается, что rvm у вас установлен, если нет, то устанавливаем.
Нам нужно две версии руби:
$ rvm install 1.9.2
$ rvm install 1.8.7
Для удобства создадим для каждого проекта свой набор гемов:
$ rvm use 1.9.2
$ rvm gemset create project
$ rvm use 1.8.7
$ rvm gemset create redmine
Соответственно получаем наборы 1.9.2@project и 1.8.7@redmine
Для того, чтобы rvm автоматически переключался на нужную версию руби и набор гемов делаем следующее:
$ echo "rvm use 1.9.2@project" > /home/username/www/project/.rvmrc
$ echo "rvm use 1.8.7@redmine" > /home/username/www/redmine/.rvmrc
Теперь в консоли при смене каталога проекта будет автоматически подключена нужная версия руби и набор гемов для проекта.
Нужно установить unicorn. Для проекта с версией рельсов от 3.0 это делается добавлением строки
gem 'unicorn'
в файл Gemfile в корне проекта и запуском
$ bundle install
В случае с редмайном, установить unicorn нужно так:
$ cd /home/username/www/redmine
$ gem install unicorn
Создаем конфиг проекта для unicorn (/home/username/www/redmine/config/unicorn.rb):
worker_processes 2
working_directory "/home/username/www/redmine/"
preload_app true
timeout 30
listen "/home/username/www/redmine/tmp/sockets/unicorn.sock", :backlog => 64
pid "/home/username/www/redmine/tmp/pids/unicorn.pid"
stderr_path "/home/username/www/redmine/log/unicorn.stderr.log"
stdout_path "/home/username/www/redmine/log/unicorn.stdout.log"
before_fork do |server, worker|
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
Делаем конфиг для другого проекта по аналогии.
Теперь нам нужно запустить unicorn как демон, для каждого проекта свой:
$ cd /home/username/www/redmine
$ unicorn_rails -c config/unicorn.rb -E production -D
$ cd /home/username/www/project
$ unicorn_rails -c config/unicorn.rb -E production -D
Осталось настроить nginx. Добавим в nginx.conf два обработчика потока (свой для каждого проекта):
...
http {
...
upstream project {
# путь должен совпадать с тем, что в конфиге unicorn.rb
server unix:/home/username/www/project/tmp/sockets/unicorn.sock;
}
upstream redmine {
server unix:/home/username/www/redmine/tmp/sockets/unicorn.sock;
}
}
Соответственно с каждого «виртуалхоста» делаем проксипасс на нужный поток, который использует соответствующий сокет юникорна.
server {
listen 80;
server_name project;
location / {
root /home/username/www/project/public;
if (!-f $request_filename) {
#делаем проксипасс на первый поток "project"
proxy_pass http://project;
break;
}
}
}
и
server {
listen 80;
server_name redmine;
location / {
root /home/username/www/redmine/public;
if (!-f $request_filename) {
#делаем проксипасс на второй поток "redmine"
proxy_pass http://redmine;
break;
}
}
}
Перезапускаем nginx. Готово.
Надеюсь кому-то пригодится и сбережет время.