Когда приложение Ruby on Rails готово к развертыванию, следует рассмотреть несколько вариантов настройки. Данный мануал поможет развернуть среду производства для приложения Ruby on Rails на основе PostgreSQL, Unicorn и Nginx в Ubuntu 14.04.
Читайте также: Развёртывание Rails-приложения при помощи Passenger и Nginx в Ubuntu 14.04
Unicorn – это сервер приложений, который позволяет Rails-приложению обрабатывать запросы. Поскольку Unicorn не предназначен для непосредственного доступа пользователей, Nginx будет использоваться в качестве обратного прокси-сервера, который будет буферизовать запросы и ответы между пользователями и Rails-приложением.
Требования
- Сервер Ubuntu 14.04, настроенный по этому мануалу. В руководстве используется условный пользователь deploy.
- Ruby on Rails, установленный с помощью rbenv (все инструкции можно найти здесь).
- СУБД PostgreSQL, настроенная для поддержки Rails (читайте мануал Приложение Ruby on Rails на PostgreSQL в Ubuntu 14.04).
В этом мануале не рассматривается настройка среды разработки или тестирования. Если вам нужна помощь в этом, следуйте руководству Приложение Ruby on Rails на PostgreSQL в Ubuntu 14.04.
1: Создание приложения Rails
В идеале у вас уже есть готовое приложение. Если это так, можете пропустить этот раздел.
Если же у вас нет приложения, создайте простое тестовое приложение Rails на БД PostgreSQL.
Эта команда создаст новое приложение Rails по имени appname, которое будет использовать PostgreSQL в качестве базы данных. Замените appname именем своего приложения.
rails new appname -d postgresql
Откройте новый каталог:
cd appname
Теперь нужно создать пользователя БД для среды производства.
2: Создание пользователя базы данных
Для простоты назовите пользователя базы данных так же, как называется ваше приложение. Например, если приложение называется «appname», создайте одноименного пользователя PostgreSQL:
sudo -u postgres createuser -s appname
Откройте консоль PostgreSQL:
sudo -u postgres psql
Затем установите пароль для пользователя базы данных appname:
\password appname
Введите свой пароль и подтвердите его.
Закройте консоль PostgreSQL:
\q
3: Настройка соединения с БД
Убедитесь, что вы в корневом каталоге приложения (cd ~/appname).
Откройте конфигурационный файл БД приложения в редакторе:
vi config/database.yml
В разделе default найдите строку pool: 5 и добавьте после нее следующую строку (если ее еще нет):
host: localhost
В конце файла вы найдете такой раздел production:
username: appname
password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
Обратите внимание, пароль базы данных хранится в переменной среды APPNAME_DATABASE_PASSWORD. Рекомендуется хранить пароли и секретные ключи производства вне кодовой базы приложения, поскольку их можно легко открыть, если вы используете систему управления версиями типа Git. Далее вы узнаете, как настроить аутентификацию базы данных с помощью переменных среды.
4: Установка плагина rbenv-vars
Перед развертыванием приложения Rails в производство нужно установить секретный ключ среды производства и пароль базы данных через переменные среды. Плагин rbenv-vars является простым средством для управления переменными среды, которое можно использовать для загрузки паролей и секретных ключей приложения.
Чтобы установить плагин rbenv-vars, просто перейдите в каталог .rbenv/plugins и клонируйте его из GitHub. Например, если rbenv установлен в домашнем каталоге, запустите следующие команды:
cd ~/.rbenv/plugins
git clone https://github.com/sstephenson/rbenv-vars.git
Установка переменных среды
После установки rbenv-vars можно установить необходимые переменные.
Сгенерируйте секретный ключ для подтверждения целостности cookies-файлов.
cd ~/appname
rake secret
Скопируйте полученный ключ и поместите его в .rbenv-vars.
vi .rbenv-vars
В этом файле Rails-приложение может читать все переменные.
Установите переменную SECRET_KEY_BASE и присвойте ей скопированный секретный ключ:
SECRET_KEY_BASE=your_generated_secret
Затем установите переменную APPNAME_DATABASE_PASSWORD; замените APPNAME именем вашего приложения, а prod_db_pass – паролем пользователя базы данных производства.
APPNAME_DATABASE_PASSWORD=prod_db_pass
Сохраните и закройте файл.
Вы можете просмотреть переменные среды приложения с помощью плагина rbenv-vars, выполнив следующую команду:
rbenv vars
Если вы измените свой секретный ключ или пароль базы данных, обновите файл .rbenv-vars. Этот файл следует хранить в секрете и не включать его в какие-либо общедоступные репозитории.
5: Создание базы данных
Создайте базу данных для производства:
RAILS_ENV=production rake db:create
Генерирование контроллера
Сгенерируйте скаффолд:
rails generate scaffold Task title:string note:text
Обновите базу данных:
RAILS_ENV=production rake db:migrate
Предварительная компиляция активов
На этом этапе приложение должно работать, но вам нужно будет предварительно скомпилировать его активы, чтобы загружать изображения, CSS и скрипты. Для этого запустите эту команду:
RAILS_ENV=production rake assets:precompile
Тестирование приложения
Чтобы проверить работу приложения, запустите среду производства и привяжите ее ко внешнему IP-адресу сервера.
RAILS_ENV=production rails server --binding=server_public_IP
Откройте в браузере этот URL:
http://server_public_IP:3000/tasks
Если все работает правильно, вы увидите:
Listing Tasks
Title Note
New Task
Вернитесь на сервер Rails и нажмите Ctrl-c, чтобы остановить приложение.
6: Установка Unicorn
Теперь нужно установить сервер приложений Unicorn.
Легкий способ сделать это – добавить его в Gemfile приложения. Откройте Gemfile в редакторе (убедитесь, что вы находитесь в корневом каталоге приложения):
vi Gemfile
Добавьте gem для Unicorn в конец файла.
gem 'unicorn'
Сохраните и закройте файл.
Чтобы установить Unicorn и зависимости, запустите:
bundle
7: Настройка сервера Unicorn
Добавьте конфигурацию Unicorn в config/unicorn.rb. Откройте этот файл в редакторе:
vi config/unicorn.rb
Скопируйте и вставьте в файл следующие строки:
# set path to application
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
working_directory app_dir
# Set unicorn options
worker_processes 2
preload_app true
timeout 30
# Set up socket location
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64
# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"
# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"
Сохраните и закройте файл. Теперь Unicorn знает, где находится приложение и логи, и какие сокеты использовать. В случае необходимости просто откорректируйте файл согласно вашим потребностям.
Создайте каталоги, на которые ссылается предыдущий файл:
mkdir -p shared/pids shared/sockets shared/log
8: Создание сценария инициализации Unicorn
Создайте сценарий инициализации, чтобы иметь возможность запускать и останавливать Unicorn и добавить его в автозагрузку.
Создайте файл и откройте его для редактирования:
sudo vi /etc/init.d/unicorn_appname
Скопируйте и вставьте в файл следующие параметры. Вместо USER и APP_NAME укажите соответствующие данные.
#!/bin/sh
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn app server
# Description: starts unicorn using start-stop-daemon
### END INIT INFO
set -e
USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"
# app settings
USER="deploy"
APP_NAME="appname"
APP_ROOT="/home/$USER/$APP_NAME"
ENV="production"
# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"
# make sure the app exists
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}
case $1 in
start)
sig 0 && echo >&2 "Already running" && exit 0
echo "Starting $APP_NAME"
su - $USER -c "$CMD"
;;
stop)
echo "Stopping $APP_NAME"
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
echo "Force stopping $APP_NAME"
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload|upgrade)
sig USR2 && echo "reloaded $APP_NAME" && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
$CMD
;;
rotate)
sig USR1 && echo rotated logs OK && exit 0
echo >&2 "Couldn't rotate logs" && exit 1
;;
*)
echo >&2 $USAGE
exit 1
;;
esac
Сохраните и закройте файл. Теперь можно использовать команду service unicorn_appname для управления сервером Unicorn и приложением Rails.
Обновите права на сценарий и добавьте Unicorn в автозагрузку:
sudo chmod 755 /etc/init.d/unicorn_appname
sudo update-rc.d unicorn_appname defaults
Запустите сервер:
sudo service unicorn_appname start
Теперь среда производства приложения обслуживается сервером Unicorn, который прослушивает сокет shared/sockets/unicorn.sock. Но пока что приложение недоступно в сети. Нужно настроить обратный прокси-сервер Nginx.
9: Установка и настройка Nginx
Установите Nginx:
sudo apt-get install nginx
Откройте виртуальный хост по умолчанию:
sudo vi /etc/nginx/sites-available/default
Замените содержимое файла следующими строками. Укажите свои данные вместо условных значений:
upstream app {
# Path to Unicorn SOCK file, as defined previously
server unix:/home/deploy/appname/shared/sockets/unicorn.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-запросы на сервер приложений Unicorn через сокет Unix.
Перезапустите Nginx:
sudo service nginx restart
Теперь приложение Rails доступно через внешний IP-адрес сервера или FQDN. Чтобы открыть контроллер Tasks, перейдите по ссылке:
http://server_public_IP/tasks
Вы должны увидеть ту же страницу, что видели ранее. Но теперь она обслуживается серверами Nginx и Unicorn.
Читайте также: Автоматизация развёртываний при помощи Capistrano