Здравствуйте, хабралюди!Хочу поделиться с вами способом разворачивания нескольких приложений 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. Готово.
Надеюсь кому-то пригодится и сбережет время.
