Фон На создание этой статьи меня побудил недавний публикация о развертывании .
В вышеприведенной статье описан метод развертывания проекта на базе rbenv, я же опишу ситуацию с rvm и настройку выскочки.
Цели и требования
Итак, дано: простейшее приложение RubyOnRails. В случае развертывания своего проекта я поставил перед собой следующие задачи:- ОС Ubuntu LTS 14.04;
- веб-сервер Nginx;
- сервер приложений Puma;
- Использование RVM для установки необходимой версии Ruby;
- Автоматический запуск приложения при запуске VPS-сервера, возможность управления приложением как сервисом;
- Автоматизация процесса развертывания с помощью mina;
Почему пума, а не единорог или пассажир? Я слышал хорошие отзывы о Puma, но у Unicron ужасный сайт. Пассажир, на мой взгляд, нарушает принцип единой ответственности — я хочу иметь веб-сервер и сервер приложений.
Почему РВМ? Я к этому привык — он у меня установлен на локальной машине, и я хочу увидеть его и в продакшене.
Почему мина? Это действительно проще, чем капистрано, и в то же время быстрее.
Скорость достигается за счет того, что capistrano создает для каждой задачи отдельное SSH-соединение.
Мина генерирует сценарий оболочки и выполняет его в рамках одного соединения.
В данном случае задачу легко разделить на 3 этапа:
- Убедитесь, что приложение запускается корректно (пока без автоматизации);
- Настройте сервер так, чтобы наше Rails-приложение работало как полноценный сервис;
- Исходя из этого, настройте автоматическое развертывание с помощью min.
Первый старт
На сервере создан пользователь веб-приложения, от имени которого будет запускаться наше приложение.Установлен rvm (в данном примере только для пользователя веб-приложения), Ruby нужной нам версии, nginx и так далее.
Gemfile содержит следующую строку:
Предварительная настройка мины Добавьте следующую строку в Gemfile:# .
gem 'puma', group: :production # .
gem 'mina', group: :development
Затем генерируем файл конфигурации командой:
mina init
Затем приведем созданный файл config/deploy.rb к следующему виду: config/deploy.rb
require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
set :domain, 'awesome_address'
set :user, 'webapp'
set :deploy_to, '/home/webapp/awesome'
set :repository, ' https://github.com/awesome_user/awesome.git '
set :branch, 'master'
set :shared_paths, ['config/database.yml', 'config/secrets.yml', 'config/puma.rb', 'log']
task :setup => :environment do
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/log"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/config"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/puma"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/puma"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/secrets.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/puma.rb"]
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml', 'secrets.yml' and puma.rb."]
end
desc "Deploys the current version to the server."
task :deploy => :environment do
deploy do
# Put things that will set up an empty directory into a fully set-up
# instance of your project.
invoke :' git:clone '
invoke :' deploy:link_shared_paths '
invoke :' bundle:install '
#invoke :' rails:db_migrate '
#invoke :' rails:assets_precompile '
#invoke :' deploy:cleanup '
end
end
Этот файл содержит закомментированные строки кода, отвечающие за выполнение рутинных операций по развертыванию проекта.
Пока мы будем выполнять эти действия вручную.
Также хочу отметить, что я не добавляю приведенный выше файл конфигурации min в контроль версий.
Затем запускаем команду: mina setup
И мы получим необходимую структуру папок на сервере, а также файлы конфигурации, которые необходимо заполнить корректными данными.
Предполагается, что вы не будете добавлять эти файлы в контроль версий, а будете хранить их исключительно на сервере.
Ниже приведен пример минимальной конфигурации для puma. puma.рб environment "production"
bind " unix:///home/webapp/awesome/shared/puma/puma.sock "
pidfile "/home/webapp/awesome/shared/puma/puma.pid"
state_path "/home/webapp/awesome/shared/puma/puma.state"
activate_control_app
Также я сознательно не храню файл puma.rb в контроле версий, потому что.
Я считаю, что конфигурация запуска сервера может быть индивидуальной, как и настройки базы данных.
На заметку, просто создайте в приложении файл config/puma.sample.rb с примером.
Теперь приступим к «развертыванию» нашего приложения: mina deploy
После выполнения этой команды на сервере появится символическая ссылка /home/webapp/awesome/current на папку с кодом нашего проекта.
Настройка nginx
Давайте создадим файл /etc/nginx/sites-available/awesome со следующим содержимым: потрясающий upstream awesome {
server unix:///home/webapp/awesome/shared/puma/puma.sock ;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /home/webapp/awesome/current/public;
server_name localhost;
location / {
proxy_pass http://awesome ;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
}
Затем мы создадим символическую ссылку: cd /etc/nginx/sites-enabled/
ln -s .
/sites-available/awesome awesome
И перезапускаем nginx: service nginx restart
Ручной запуск приложения
Теперь подготовим и запустим наш проект.
Мы готовы: cd /home/webapp/awesome/current
bash --login
rvm use ruby-2.2.1
bundle install --without development:test --path .
/vendor/bundle --deployment
RAILS_ENV=production bundle exec rake db:migrate
RAILS_ENV=production bundle exec rake assets:precompile
Запустим: bundle exec puma -C config/puma.rb
Открываем проект в браузере — всё должно работать.
Приложение как услуга
Чтобы приложение работало как служба и запускалось при старте/перезагрузке системы, необходимо создать скрипт init.d или конфигурацию выскочки.Я выбрал выскочку, потому что полученный файл намного короче и его легче понять.
Чтобы правильно подключить выскочку и рвм, создать обертку для исполняемых файлов наших гемов: rvm alias create awesome ruby-2.2.1@default
Затем мы создаем конфигурацию выскочки /etc/init/awesome.conf: Awesome.conf description "Awesome puma service"
# This starts upon bootup and stops on shutdown
start on runlevel [2345]
stop on runlevel [06]
setuid webapp
setgid webapp
respawn
respawn limit 3 30
script
cd /home/webapp/awesome/current
/home/webapp/.
rvm/wrappers/awesome/bundle exec puma -C config/puma.rb
end script
И теперь мы можем сделать это: start awesome
stop awesome
restart awesome
status awesome
Окончательная автоматизация
Поскольку развертывание будет происходить от имени пользователя веб-приложения, а для перезапуска сервиса нужны права суперпользователя, то добавим соответствующую строку в sudoers. Давайте запустим команду: visudo
Добавлять:
webapp ALL=(ALL) NOPASSWD: /sbin/start awesome, /sbin/stop awesome, /sbin/restart awesome, /sbin/status awesome
И мы экономим.
И снова мина В таких случаях mina предлагает использовать собственный модуль mina/rvm, но rvm дает нам возможность создавать псевдонимы для версий Ruby и гемсетов — оберток.
Чтобы при развертывании запускался сборщик оберток, нужно добавить следующую строку: set :bundle_bin, '/home/webapp/.
rvm/wrappers/awesome/bundle'
Добавим еще задачу на перезапуск сервера: desc "Restart the puma web server."
task :restart do
queue 'sudo restart awesome'
end
Добавив все это и раскомментировав нужные строки в задаче развертывания, получим следующее: Deploy.rb require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
set :domain, 'awesome_address'
set :user, 'webapp'
set :deploy_to, '/home/webapp/awesome'
set :repository, ' https://github.com/awesome_user/awesome.git '
set :branch, 'master'
set :bundle_bin, '/home/webapp/.
rvm/wrappers/awesome/bundle'
set :shared_paths, ['config/database.yml', 'config/secrets.yml', 'config/puma.rb', 'log']
task :setup => :environment do
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/log"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/config"]
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/puma"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/puma"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/secrets.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/puma.rb"]
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml', 'secrets.yml' and puma.rb."]
end
desc "Deploys the current version to the server."
task :deploy => :environment do
deploy do
# Put things that will set up an empty directory into a fully set-up
# instance of your project.
invoke :' git:clone '
invoke :' deploy:link_shared_paths '
invoke :' bundle:install '
invoke :' rails:db_migrate '
invoke :' rails:assets_precompile '
invoke :' deploy:cleanup '
to :launch do
invoke :'restart'
end
end
end
desc "Restart the puma web server."
task :restart do
queue 'sudo restart awesome'
end
Все готово!
Теперь мы можем снова запустить развертывание проекта и посмотреть на результат: mina deploy
Альтернативы
В качестве альтернативы можно рассмотреть Пума-джунгли .Это шаблоны скриптов upstart и init.d, которые корректно работают с rbenv, rvm и другими менеджерами версий.
В случае с rvm необходимо убедиться, что версия Ruby и gemset, если они используются, определены правильно — для этого можно использовать файлы .
ruby-version и .
ruby-gemset.
Вы можете поместить их в систему контроля версий, а можете создать во время развертывания через mina. Вам также придется использовать библиотеку mina/rvm и создать задачу для установки правильной версии Ruby и Gemset.
Все вместе это может выглядеть так: Deploy.rb # .
# Rvm ruby version and gemset rvm = { ruby_version: 'ruby-2.2.1', ruby_gemset: 'default' } task :environment do invoke :"rvm:use[#{rvm[:ruby_version]}@#{rvm[:ruby_gemset]}]" end # .
desc "Creates appropriate .
ruby-version and .
ruby-gemset files." task :'rvm:dot_files' do queue! %[echo "#{rvm[:ruby_version]}" > .
ruby-version] queue! %[echo "#{rvm[:ruby_gemset]}" > .
ruby-gemset] end task :setup => :environment do # .
end task :deploy => :environment do deploy do invoke :'git:clone' invoke :'rvm:dot_files' # .
end end # .
Конец
На этом моя публикация заканчивается.Надеюсь, это было интересно и полезно.
Теги: #rails #rvm #Upstart #mina #puma #ubuntu #ruby onrails
-
Полезная Usb-Ссылка Go
19 Oct, 24