Развертывание Rails-приложения на Capistrano, Nginx и Puma в Ubuntu 14.04

Rails – это открытый фреймворк Ruby для разработки веб-приложений. Rails следует соглашениям по конфигурации, предполагая, что существует «лучший» способ решить ту или иную задачу. Это позволяет реализовать больше функций при помощи меньшего количества кода и конфигурационных файлов.

Nginx – это высокопроизводительный HTTP-сервер, обратный прокси-сервер и балансировщик нагрузки; его основные качества – параллельная обработка, надежность, масштабируемость и низкое потребление памяти. Puma – еще один быстрый веб-сервер с поддержкой параллельной обработки и потреблением небольшого объема памяти. Сервер Puma разработан для веб-приложений Ruby.

Capistrano – это инструмент для автоматизации задач на удаленном сервере, ориентированный в основном на веб-приложения Ruby. Он развертывает веб-приложения на удаленных компьютерах путем запуска рабочих процессов по SSH и автоматизации общих задач, таких как предварительная компиляция исходногокода и перезапуск сервера Rails.

Данный мануал поможет установить Ruby и Nginx на сервер Ubuntu и настроить Puma и Capistrano для обработки приложения. Nginx будет перехватывать пользовательские запросы и передавать их серверу Puma, на котором будет запущен Rails. Capistrano автоматизирует общие задачи развертывания, благодаря чему развертывание каждой новой версии Rails-приложения можно выполнить с помощью нескольких простых команд.

Требования

  • Сервер Ubuntu 14.04, настроенный по этому мануалу.
  • Готовое к развертыванию рабочее приложение Rails в удаленном репозитории git.
  • Опционально: для повышенной безопасности вы можете отключить аутентификацию root через SSH и изменить номер порта SSH. В этом вам поможет мануал Начальная настройка сервера Ubuntu 14.04.

Важно! Отключив логин root, убедитесь, что можете подключиться к серверу как пользователь с доступом к sudo (в этом мануале он называется deploy).

1: Установка Nginx

Обновите индекс пакетов:

sudo apt-get update

Установите Nginx:

sudo apt-get install curl git-core nginx -y

2: Установка баз данных

Теперь установите БД для своего Rails-приложения. Для этого существует множество СУБД, потому мы не будем описывать установку подробно. Все необходимые инструкции в сможете найти в специальных разделах нашего Информатория. Рекомендуем обратиться к этим руководствам:

3: Установка RVM и Ruby

Не нужно устанавливать Ruby напрямую. Для этого лучше использовать менеджер RVM, Ruby Version Manager. Существует несколько его версий (rbenv, chruby и т.п.), но в этом мануале используется RVM. RVM позволяет легко устанавливать и управлять несколькими версиями Ruby в одной системе. Это особенно полезно, когда вам нужно обновить версию Ruby, которую использует приложение Rails.

Прежде чем установить RVM, импортируйте GPG-ключ:

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

Установите RVM:

curl -sSL https://get.rvm.io | bash -s stable

Команда curl загрузит установочный сценарий RVM по ссылке https://get.rvm.io. Опция –sSL состоит из трех флагов:

  • -s: загружает файл в немом режиме.
  • -S: выводит сообщения об ошибках, если таковые случаются.
  • -L: за всеми перенаправлениями HTTP при получении сценария установки.

После загрузки сценарий отправляется в bash. Параметр -s передает stable как аргумент сценария RVM для загрузки и установки стабильной версии RVM.

Примечание: Если вторая команда выдает GPG signature verification failed, это означает, что ключ GPG изменился. Просто скопируйте команду из вывода и запустите ее для загрузки подписей. Затем запустите команду curl для установки RVM.

Нужно загрузить сценарий RVM (как функцию), чтобы начать его использовать. Затем нужно запустить команду requirements для автоматической установки необходимых зависимостей и файлов RVM и Ruby:

source ~/.rvm/scripts/rvm
rvm requirements

Теперь можно установить Ruby (в данном мануале используется версия Ruby 2.2.1).

rvm install 2.2.1
rvm use 2.2.1 --default

4: Установка Rails и Bundler

Теперь можно установить gem-ы. для начала установите gem для Rails, который позволит запустить приложение Rails. Затем установите bundler, который будет читать файл Gemfile и автоматически устанавливать необходимые gem-ы.

gem install rails -V --no-ri --no-rdoc
gem install bundler -V --no-ri --no-rdoc

В командах используются такие флаги:

  • -V отображает подробный вывод об установке Gem-ов.
  • —no-ri пропускает установку документов Ri, что помогает сэкономить пространство и быстрее закончить установку.
  • —no-rdoc пропускает RDocs.

Примечание: Также можно установить конкретную версию Rails с помощью флага –v:

gem install rails -v '4.2.0' -V --no-ri --no-rdoc

5: SSH-ключи

Чтобы настроить корректное развертывание, нужно добавить аутентификацию на основе SSH-ключей.

Подключитесь к GitHub, Bitbucket или другому удаленному репозиторию Git, где хранится база кода вашего приложения Rails:

ssh -T git@github.com
ssh -T git@bitbucket.org

Не беспокойтесь, если вы получите сообщение Permission denied (publickey). Теперь создайте ключ SSH (пару из открытого и закрытого ключа):

ssh-keygen -t rsa

Добавьте новый открытый ключ (~/.ssh/id_rsa.pub) в параметры репозитория.

После этого у вас появится возможность клонировать git-репозиторий по SSH без пароля:

git clone git@example.com:username/appname.git

Если вам нужно простое приложение для тестирования, вы можете использовать следующее тестовое приложение на GitHub.

Команда git clone создаст каталог с тем же именем, что и у приложения (например, каталог с именем testapp_rails).

На данном этапе клонирование позволяет убедиться, что ключи работают. Клонировать или выгружать репозиторий при каждом изменении не нужно. Это все может делать Capistrano. Теперь можно удалить клонированный каталог.

Откройте терминал на локальной машине. Если у вас нет  SSH-ключей для локального компьютера, создайте их. Введите:

ssh-keygen -t rsa

Добавьте локальные SSH-ключи в файл authorized_keys на удаленном сервере (не забудьте указать правильный номер порта).

cat ~/.ssh/id_rsa.pub | ssh -p your_port_num deploy@your_server_ip 'cat >> ~/.ssh/authorized_keys'

6: Настройка развертывания приложения

На локальной машине создайте конфигурационные файлы для Nginx и Capistrano в каталоге приложения Rails. Добавьте в Gemfile эти строки:

group :development do
gem 'capistrano',         require: false
gem 'capistrano-rvm',     require: false
gem 'capistrano-rails',   require: false
gem 'capistrano-bundler', require: false
gem 'capistrano3-puma',   require: false
end
gem 'puma'

Используйте bundler для установки gem-ов из Gemfile. Введите команду:

bundle

Затем запустите эту команду, чтобы настроить Capistrano:

cap install

Команда создаст:

  • Capfile в корневом каталоге приложения Rails.
  • Файл deploy.rb в каталоге config.
  • Каталог deploy в каталоге config.

Замените содержимое Capfile следующими строками:

# Load DSL and Setup Up Stages
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rails'
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/puma'
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Этот Capfile загружает предопределенные задачи в конфигурационные файлы Capistrano, чтобы автоматизировать развертывания. Среди этих задач:

  • Выбор правильной версии Ruby
  • Предварительная компиляция активов
  • Клонирование хранилища Git в правильное место
  • Установка новых зависимостей при изменении Gemfile

Замените содержимое config/deploy.rb следующими строками; в полях, отмеченных красным, укажите параметры приложения и сервера:

# Change these
server 'your_server_ip', port: your_port_num, roles: [:web, :app, :db], primary: true
set :repo_url,        'git@example.com:username/appname.git'
set :application,     'appname'
set :user,            'deploy'
set :puma_threads,    [4, 16]
set :puma_workers,    0
# Don't change these unless you know what you're doing
set :pty,             true
set :use_sudo,        false
set :stage,           :production
set :deploy_via,      :remote_cache
set :deploy_to,       "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :puma_bind,       "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state,      "#{shared_path}/tmp/pids/puma.state"
set :puma_pid,        "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.error.log"
set :puma_error_log,  "#{release_path}/log/puma.access.log"
set :ssh_options,     { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true  # Change to false when not using ActiveRecord
## Defaults:
# set :scm,           :git
# set :branch,        :master
# set :format,        :pretty
# set :log_level,     :debug
# set :keep_releases, 5
## Linked Files & Directories (Default None):
# set :linked_files, %w{config/database.yml}
# set :linked_dirs,  %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
namespace :puma do
desc 'Create Directories for Puma Pids and Socket'
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
desc "Make sure local git is in sync with remote."
task :check_revision do
on roles(:app) do
unless `git rev-parse HEAD` == `git rev-parse origin/master`
puts "WARNING: HEAD is not the same as origin/master"
puts "Run `git push` to sync changes."
exit
end
end
end
desc 'Initial Deploy'
task :initial do
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
invoke 'puma:restart'
end
end
before :starting,     :check_revision
after  :finishing,    :compile_assets
after  :finishing,    :cleanup
after  :finishing,    :restart
end
# ps aux | grep puma    # Get puma pid
# kill -s SIGUSR2 pid   # Restart puma
# kill -s SIGTERM pid   # Stop puma

Этот файл содержит параметры по умолчанию, которые помогут управлять релизами приложения и автоматически выполнят некоторые задачи развертывания. Файл:

  • Устанавливает production как среду по умолчанию для приложения Rails.
  • Может автоматически управлять релизами приложения.
  • Использует оптимизированную опцию SSH.
  • Проверяет актуальность удаленных репозиториев git.
  • Управляет логами приложения.
  • Предварительно загружает приложение в память для управления рабочими процессами Puma.
  • Запускает/перезапускает сервер Puma после завершения развертывания.
  • Открывает сокет сервера Puma.

Вы можете изменить параметры в зависимости от ваших требований. Теперь необходимо настроить Nginx. Создайте config/nginx.conf в каталоге проекта Rails и вставьте в файл следующее (опять же, указав ваши параметры):

upstream puma {
server unix:///home/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock;
}
server {
listen 80 default_server deferred;
# server_name example.com;
root /home/deploy/apps/appname/current/public;
access_log /home/deploy/apps/appname/current/log/nginx.access.log;
error_log /home/deploy/apps/appname/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @puma;
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
}

Как и предыдущий файл, этот файл содержит параметры по умолчанию, которые могут взаимодействовать с файлом deploy.rb. Он прослушивает трафик на порту 80 и передает запрос на сокет Puma, записывает логи nginx в текущую версию приложения, сжимает все активы и кэширует их в браузере с максимальным сроком действия, обслуживает HTML-страницы в общедоступной папке как статические файлы и устанавливает максимальные значения Client Body Size и Request Timeout.

7: Развертывание приложения Rails

Если вы используете свое собственное приложение, отправьте все изменения в удаленный репозиторий:

git add -A
git commit -m "Set up Puma, Nginx & Capistrano"
git push origin master

Примечание: Если в этой системе вы используете GitHub впервые, вам, возможно, понадобится выполнить следующие команды, указав имя пользователя GitHub и свой адрес электронной почты.

git config --global user.name 'Your Name'
git config --global user.email you@example.com

На локальной машине запустите первое развертывание:

cap production deploy:initial

Эта команда загрузит приложение Rails на сервер, установит все необходимые gem-ы и запустит веб-сервер Puma. Это займет от 5 до 15 минут в зависимости от количества Gem-ов, которые вы используете в приложении. Вы увидите отладочные сообщения по мере возникновения ошибок.

Если все прошло правильно, теперь можно подключить веб-сервер Puma к обратному прокси-серверу Nginx.

На сервере создайте символьную ссылку на nginx.conf в sites-enabled:

sudo rm /etc/nginx/sites-enabled/default
sudo ln -nfs "/home/deploy/apps/appname/current/config/nginx.conf" "/etc/nginx/sites-enabled/appname"

Перезапустите Nginx:

sudo service nginx restart

Теперь вы можете запросить в браузере IP-адрес сервера и получить доступ к своему приложению Rails.

Дополнительные рекомендации

Всякий раз, когда вы вносите изменения в свое приложение и хотите развернуть новую версию на сервере, нужно отправить сообщение о коммите, загрузить изменения в удаленный репозиторий git и запустить команду deploy:

git add -A
git commit -m "Deploy Message"
git push origin master
cap production deploy

Примечание: Если вы вносите изменения в config/nginx.conf, нужно перезапустить Nginx на сервере после развертывания приложения:

sudo service nginx restart

Заключение

Теперь ваше Rails-приложение развернуто на удаленном сервере. Для обслуживания приложения используется сервер Puma и обратный прокси Nginx. Capistrano автоматизирует развертывания.

Читайте также:

Tags: , , , ,