Рассмотрим установку на сервере приложения с Nginx Unicorn, первый будет использоваться на фронтэнде, второй представлять собой бэкенд. Приложение работает в виртуальной среде vagrant, но если оно единственное на сервере и виртуализация не используется принципы сохраняются.
Предполагается, что на сервере уже установлен RVM и Ruby, а также имеется написанное приложение, которое и будем запускать. Также установлены гемы Unicorn и rails.
Установка проекта на Ruby-on-rails со связкой Nginx Unicorn
Проверяем версию Ruby, используемую по умолчанию
ruby -v
Переходим в каталог с проектом на Ruby-on-rails
cd /home/vagrant
Запускаем проект на порту 3000
bundle exec rails s
После выполнения команды в браузере по адресу localhost:3000 приложение на rails станет доступно
Устанавливаем и запускаем nginx
apt-get install nginx
/etc/init.d/nginx start
В vagrant настраиваем forward-инг с порта 80 на 8080
mcedit Vagrantfile
config.vm.forward_port «rails», 80, 8080
Перезапускаем
vagrant reload
Проверяем localhost:8080. Можно использовать любой другой свободный порт, но в данном случае Nginx будет переадресовывать запросы на порт 8080, на котором и будет работать приложение
cd /etc/nginx
Удаляем конфиг сайта по-умолчанию в Nginx
rm /etc/nginx/sites-enabled/default
Создаем новый
mcedit /etc/nginx/sites-enabled/app.conf
server {
listen 80 default;
#server_name example.com;
root /home/vagrant/public;
}
Делаем символьную ссылку на конфиг проекта и перезапускаем Nginx
ln -s /home/vagrant/config/nginx.conf app
/etc/init.d/nginx restart
На данном этапе статика должна отдаваться, чтобы отдавался и динамический контент отредактируем конфиг Nginx задав подключение к Unicorn
mcedit /etc/nginx/sites-enabled/app.conf
server {
listen 80 default;
#server_name example.com;
root /home/vagrant/public;
try_files $uri/index.html $uri $uri @unicorn;
location @unicorn {
proxy_pass http://localhost:3000
}
}
Перезапускаем Nginx и стартуем приложение
/etc/init.d/nginx restart
bundle exec rails s
Обратившись к localhost:8080 сейчас можно увидеть полностью фракционирующее приложение, оно уже работает на связке Nginx Unicorn, хотя для продакшн такое решение пока использовать нельзя.
Добавим страницу с ошибкой сервера в конфиг.
mcedit /etc/nginx/sites-enabled/app.conf
server {
listen 80 default;
#server_name example.com;
root /vagrant/public;
try_files $uri/index.html $uri $uri @unicorn;
location @unicorn {
proxy_pass http://localhost:3000
}
error_page 500 502 503 504 /500.html;
}
Как настроить Unicorn
Предполагалось, что Unicorn уже работает, но если это не так его можно запустить раскомментировав gem 'unicorn' в Gemfile
Затем выполнить команду bundle чтобы установить
bundle
Создаем конфигурационный файл Unicorn
mcedit config/unicorn.rb
working directory «vagrant»
pid «/vagrant/tmp/pids/unicorn.pid»
stderr-path «vagrant/log/unicorn.log»
stdout-path «vagrant/log/unicorn.log»
listen «/tmp/unicorn.app.sock»
worker_processes 2
timout 30
Вместо сокета можно указать адрес и порт.
Запускаем указывая конфиг с опцией -c и ключом -D чтобы сделать процесс демоном
bundle exec unicorn -c config/unicorn.rb -D
Далее определяем upstream и задаем некоторые дополнительные параметры
mcedit /etc/nginx/sites-enabled/app.conf
upstream unicorn {
server unix:/tmp/unicorn.todo.sock fail_timeout=0;
}
server {
listen 80 default deffered;
#server_name example.com;
root /home/vagrant/public;
try_files $uri/index.html $uri $uri @unicorn;
location @unicorn {
proxy-set_header X-Forwarded_for $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
error_page 500 502 503 504 /500.html;
clien_max_body_size 4G;
keepalive_timeout 10;
}
Перезапускаем Nginx
/etc/init.d/nginx restart
Далее потребуется создать инициализационный скрипт для Unicorn
Его можно скачать по адресу https://github.com/defunkt/unicorn/blob/master/examples/init.sh
mcedit config/unicorn_init.sh
В скрипт вносим изменения:
-
- меняем APP_ROOT
- проверяем путь к PID
- проверяем команду CMD (в примере использовали bundler, поэтому меняем на -bundle install —binstubs, что сгенерирует директрию для бинарных файлов приложения
- INIT_CONF удаляем;
- по умолчанию скрипты выполняется от рута, если хотим поменять на пользователя vagrant, тодоавляем следующий блок:
start)
sig 0 && echo >&2 «Already running» && exit 0
su -c «$CMD» — vagrant меняем в инит скрипте для всех вхождений)
Инициализационный скрипт после внесения коррективов должен выглядеть так:
#!/bin/sh
set -e
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/vagrant
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD=»/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb»
INIT_CONF=$APP_ROOT/config/init.conf
UPGRADE_DELAY=${UPGRADE_DELAY-2}
action=»$1"
set -utest -f «$INIT_CONF» && . $INIT_CONFOLD=»$PID.oldbin»cd $APP_ROOT || exit 1sig () {
test -s «$PID» && kill -$1 $(cat $PID)
}oldsig () {
test -s «$OLD» && kill -$1 $(cat $OLD)
}case $action in
start)
sig 0 && echo >&2 «Already running» && exit 0
su -c «$CMD» — vagrant
;;
stop)
sig QUIT && exit 0
echo >&2 «Not running»
;;
force-stop)
sig TERM && exit 0
echo >&2 «Not running»
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 «Couldn't reload, starting '$CMD' instead»
su -c «$CMD» — vagrant
;;
upgrade)
if oldsig 0
then
echo >&2 «Old upgraded process still running with $OLD»
exit 1
ficur_pid=
if test -s «$PID»
then
cur_pid=$(cat $PID)
fiif test -n «$cur_pid» &&
kill -USR2 «$cur_pid» &&
sleep $UPGRADE_DELAY &&
new_pid=$(cat $PID) &&
test x»$new_pid» != x»$cur_pid» &&
kill -0 «$new_pid» &&
kill -QUIT «$cur_pid»
then
n=$TIMEOUT
while kill -0 «$cur_pid» 2>/dev/null && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n — 1 ))
done
echoif test $n -lt 0 && kill -0 «$cur_pid» 2>/dev/null
then
echo >&2 «$cur_pid still running after $TIMEOUT seconds»
exit 1
fi
exit 0
fi
echo >&2 «Couldn't upgrade, starting '$CMD' instead»
su -c «$CMD» — vagrant
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 «Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>»
exit 1
;;
esac
Делаем скрипт исполняемым
chmod +x config-unicorn/init.sh
Содаем символьную ссылку для того чтобы управлять Unicorn как любым другим сервисом через /etc/ini.t/SERVICENAME start|stop|restart
sudo ln -s /vagrant/config/unicorn_init.sh /etc/init.d/unicorn
Перезапускаем unicorn, vagrant, затем Nginx
sudo /etc/init.d/unicorn restart
vagrant reload
sudo /etc/init.d/nginx restart
С приведенным init-скриптом приложение работает в режиме DEVELOPMENT, чтобы сменить режим на PRODUCTION в конфиге нужно поправить одну строку приведя ее к виду:
scriptCMD=»/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb -E production»
Nginx Unicorn является самой распространенной связкой для деплоя Ruby проектов, но существуют и другие варианты — например, Unicorn с Apache