Развертывание приложения Rails в Ubuntu 14.04 с помощью Capistrano, Nginx и Puma
Введение
Rails — это фреймворк для веб-приложений с открытым исходным кодом, написанный на Ruby. Он следует философии Конвенция важнее конфигурации, делая предположения о том, что существует «лучший» способ ведения дел. Это позволяет вам писать меньше кода, выполняя больше, не просматривая бесконечные файлы конфигурации.
Nginx — это высокопроизводительный HTTP-сервер, обратный прокси-сервер и балансировщик нагрузки, известный своей ориентацией на параллелизм, стабильность, масштабируемость и низкое потребление памяти. Как и Nginx, Puma — еще один чрезвычайно быстрый и параллельный веб-сервер с очень небольшим объемом памяти, но созданный для веб-приложений Ruby.
Capistrano — это инструмент автоматизации удаленного сервера, ориентированный в основном на веб-приложения Ruby. Он используется для надежного развертывания веб-приложений на любом количестве удаленных компьютеров путем написания сценариев произвольных рабочих процессов через SSH и автоматизации общих задач, таких как предварительная компиляция ресурсов и перезапуск сервера Rails.
В этом руководстве мы установим Ruby и Nginx на дроплет DigitalOcean Ubuntu и настроим Puma и Capistrano в нашем веб-приложении. Nginx будет использоваться для захвата клиентских запросов и передачи их на веб-сервер Puma, на котором работает Rails. Мы будем использовать Capistrano для автоматизации общих задач развертывания, поэтому каждый раз, когда нам нужно развертывать новую версию нашего приложения Rails на сервере, мы можем делать это с помощью нескольких простых команд.
Предпосылки
Чтобы следовать этому руководству, у вас должно быть следующее:
- Дроплет Ubuntu 14.04 x64
- Пользователь без полномочий root с именем
deploy
с привилегиями sudo (начальная настройка сервера с Ubuntu 14.04 объясняет, как это настроить). - Рабочее приложение Rails, размещенное в удаленном репозитории git, готовое к развертыванию
При желании для повышения безопасности вы можете отключить вход в систему root через SSH и изменить номер порта SSH, как описано в разделе «Начальная настройка сервера с Ubuntu 14.04».
Предупреждение. После отключения входа в систему с правами root убедитесь, что вы можете использовать SSH для доступа к своей капле в качестве пользователя deploy
и использовать sudo
для этого пользователя, перед закрытием root Сеанс SSH, который вы открыли для внесения этих изменений.
Все команды в этом руководстве следует запускать от имени пользователя deploy
. Если для команды требуется root-доступ, ей будет предшествовать sudo
.
Шаг 1 — Установка Nginx
Как только VPS будет защищен, мы можем начать установку пакетов. Обновите индексные файлы пакета:
- sudo apt-get update
Затем установите Nginx:
- sudo apt-get install curl git-core nginx -y
Шаг 2 — Установка баз данных
Установите базу данных, которую вы будете использовать в своем приложении Rails. Поскольку существует множество баз данных на выбор, мы не будем рассматривать их в этом руководстве. Вы можете увидеть инструкции для основных здесь:
- Майкл
- PostgreSQL
- МонгоБД
Также обязательно ознакомьтесь:
- Как использовать MySQL с приложением Ruby on Rails в Ubuntu 14.04
- Как использовать PostgreSQL с приложением Ruby on Rails в Ubuntu 14.04
Шаг 3 — Установка RVM и Ruby
Мы не будем устанавливать Ruby напрямую. Вместо этого мы будем использовать Ruby Version Manager. Их много на выбор (rbenv, chruby и т. д.), но для этого урока мы будем использовать RVM. RVM позволяет вам легко устанавливать и управлять несколькими рубинами в одной системе и использовать правильный в соответствии с вашим приложением. Это значительно упрощает жизнь, когда вам нужно обновить приложение Rails, чтобы использовать более новый ruby.
Перед установкой RVM вам необходимо импортировать ключ 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
указывает curl загружать файл в «автоматическом режиме»-S
указывает curl показывать сообщение об ошибке в случае сбоя-L
указывает curl следовать всем перенаправлениям HTTP при получении скрипта установки
После загрузки скрипт передается в bash
. Опция -s
передает stable
в качестве аргумента сценарию установки RVM для загрузки и установки стабильной версии RVM.
Примечание. Если вторая команда завершается с ошибкой с сообщением «Ошибка проверки подписи GPG», это означает, что ключ GPG был изменен, просто скопируйте команду из вывода ошибки и запустите ее, чтобы загрузить подписи. Затем запустите команду curl для RVM. Монтаж.
Нам нужно загрузить скрипт RVM (как функцию), чтобы мы могли начать его использовать. Затем нам нужно запустить команду requirements
, чтобы автоматически установить необходимые зависимости и файлы для правильной работы RVM и Ruby:
- source ~/.rvm/scripts/rvm
- rvm requirements
Теперь мы можем установить Ruby по нашему выбору. Мы установим последнюю версию Ruby 2.2.1
(на момент написания статьи) в качестве Ruby по умолчанию:
- rvm install 2.2.1
- rvm use 2.2.1 --default
Шаг 4 — Установка Rails и Bundler
Как только Ruby настроен, мы можем начать установку Rubygems. Мы начнем с установки гема Rails, который позволит запускать ваше приложение Rails, а затем мы установим bundler
, который может читать Gemfile
вашего приложения и автоматически устанавливать все необходимые драгоценные камни.
Чтобы установить Rails и Bundler:
- gem install rails -V --no-ri --no-rdoc
- gem install bundler -V --no-ri --no-rdoc
Использовались три флага:
-V
(подробный вывод): выводит подробную информацию об установке Gem--no-ri
— (пропускает документацию Ri): не устанавливает Ri Docs, экономит место и ускоряет установку--no-rdoc
— (пропускает RDocs): не устанавливает RDocs, что экономит место и ускоряет установку
Примечание. Вы также можете установить конкретную версию Rails в соответствии с вашими требованиями, используя флаг -v
:
- gem install rails -v '4.2.0' -V --no-ri --no-rdoc
Шаг 5 — Настройка ключей SSH
Поскольку мы хотим настроить плавное развертывание, мы будем использовать ключи SSH для авторизации. Сначала пожмите руку GitHub, Bitbucket или любому другому Git Remote, где размещена база кода для вашего приложения Rails:
- ssh -T git@github.com
- ssh -T git@bitbucket.org
Не беспокойтесь, если вы получите сообщение Отказано в доступе (publickey)
. Теперь сгенерируйте SSH-ключ (пару открытого и закрытого ключей) для вашего сервера:
- ssh-keygen -t rsa
Добавьте только что созданный открытый ключ (~/.ssh/id_rsa.pub
) в ключи развертывания вашего репозитория:
- Инструкции для Github
- Инструкции для Bitbucket
Если все шаги были выполнены правильно, теперь вы сможете клонировать
свой репозиторий git (по протоколу SSH, а не HTTP) без ввода пароля:
- git clone git@example.com:username/appname.git
Если вам нужен образец приложения для тестирования, вы можете разветвить следующее тестовое приложение, специально созданное для этого руководства: Образец приложения Rails на GitHub
Команда git clone
создаст каталог с тем же именем, что и ваше приложение. Например, будет создан каталог с именем testapp_rails
.
Мы клонируем только для того, чтобы проверить, работают ли наши ключи развертывания, нам не нужно клонировать или извлекать наш репозиторий каждый раз, когда мы вносим новые изменения. Мы позволим Капистрано справиться со всем этим за нас. Теперь вы можете удалить этот клонированный каталог, если хотите.
Откройте терминал на локальном компьютере. Если у вас нет ключа SSH для локального компьютера, создайте его и для него. В вашем локальном терминальном сеансе:
- ssh-keygen -t rsa
Добавьте свой локальный SSH-ключ в файл Авторизованные ключи вашего дроплета (не забудьте заменить номер порта вашим настроенным номером порта):
- cat ~/.ssh/id_rsa.pub | ssh -p your_port_num deploy@your_server_ip 'cat >> ~/.ssh/authorized_keys'
Шаг 6 — Добавление конфигураций развертывания в приложение Rails
На локальном компьютере создайте файлы конфигурации для Nginx и Capistrano в приложении Rails. Начните с добавления этих строк в Gemfile
в приложении Rails:
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
для установки драгоценных камней, которые вы только что указали в своем Gemfile
. Введите следующую команду, чтобы связать ваше приложение Rails:
- 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
Этот файл deploy.rb
содержит несколько нормальных настроек по умолчанию, которые работают «из коробки», чтобы помочь вам управлять выпусками приложений и автоматически выполнять некоторые задачи при развертывании:
- Использует
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;
}
Как и в предыдущем файле, этот nginx.conf
содержит настройки по умолчанию, которые готовы к работе с конфигурациями в вашем файле deploy.rb
. Это прослушивает трафик на порту 80 и передает запрос в ваш сокет Puma, записывает журналы nginx в «текущий» выпуск вашего приложения, сжимает все активы и кэширует их в браузере с максимальным сроком действия, обслуживает HTML-страницы в общедоступном как статические файлы и устанавливает максимальные значения Client Body Size
и Время ожидания запроса
по умолчанию.
Шаг 7 — Развертывание вашего приложения Rails
Если вы используете свое собственное приложение 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 в Droplet, установит все необходимые драгоценные камни для вашего приложения и запустит веб-сервер Puma. Это может занять от 5 до 15 минут в зависимости от количества Gems, которое использует ваше приложение. По мере выполнения этого процесса вы будете видеть отладочные сообщения.
Если все пойдет гладко, теперь мы готовы подключить ваш веб-сервер 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 с базовыми настройками. Теперь вы должны взглянуть на другие документы, которые могут помочь вам оптимизировать ваши конфигурации, чтобы получить максимальную отдачу от вашего приложения Rails:
- Конфигурации Puma
- Puma DSL в Капистрано
- Предварительная компиляция локальных активов в Capistrano
- Автоматически перезапускать рабочие процессы Puma в зависимости от объема оперативной памяти.
- Оптимизация Nginx для высоких нагрузок