Настройка Rails приложения для развертывания на нашем хостинге, часть 2

  • написал: MpaK
  • 122


В первой части, я описал процесс установки нужных нам компонент для развертывания множества веб-приложений на базе Ruby on Rails на нашем сервере — ufacode.ru/blog/linux/1100.html

В этой части я хочу показать простую конфигурацию нашего приложения для работы с Capistrano (деплой инструмент) и Unicorn (быстрый веб-сервер).

И так, у нас уже есть созданный Rails проект, нам надо установить наши модули Capistrano и Unicorn для нужных нам сред, для этого редактируем файл Gemfile в корне и добавляем строки.
group :production do
  gem 'unicorn'
end

group :development do
  gem 'rvm-capistrano'
  gem 'capistrano'
end

в первом блоке мы указываем, что для продакшен окружения надо будет установить unicorn веб-сервер, во-втором блоке, что в окружении разработчика нам нужны библиотеки capistrano.

После чего запускаем установку библиотек заново
bundle install


Теперь все на борту и надо конфигурировать, набираем в консоли:
capify .

после чего у нас в папке приложения config/deploy.rb создается конфигурационный файл, все его премудрости можно постичь прочитав мануал — github.com/capistrano/capistrano/wiki

А я приведу просто с комментариями свой типовой файл.
Надо оговорить сразу как работает Capistrano при развертывании, какие действия совершает и откуда появляется исходный код вашего приложения на вашем сервере.
— при запуске развертыания он читает ваш конфиг, находит по директивам какая система контроля версий используется в вашем проекте (git, svn...)
— далее он заходит на ваш рабочий сервер и выкачивает исходники с сервера версий (github, gitbucket и т.п.)
— под конец запускает всяческие директивы на конфугурирование, на миграции, на запуск и остановку веб-сервера (unicorn, thin, puma и т.п.)

Хороший подход, но часто я мухлюю и мне неудобно развертывать например с закрытых проектов на bitbucket, мне проще делать копию сразу с локального компьютера, и в этом случае для Capistrano нет проблем тоже, в моем файле это видно.
Оговорю сразу, что ряд вещей надо будет вам отключать или переписывать, читайте логи ошибок и интернет вам всегда поможет.

Файл config/deploy.rb
require "rvm/capistrano"
require "bundler/capistrano"
load 'deploy/assets'

set :application, "project_name" # название проекта, будет распологаться /home/deployer/project_name

set :scm, :git
set :repository,  "."  # в моем случае ссылки к репозитарию нет
set :deploy_via, :copy # и мы развертываем простым копированием
set :copy_cache, true

set :deploy_server,   "my-mega-server.ru" # здесь IP или host нашего сервера для развертывания
set :bundle_without,  [:development, :test] # указываем какие среды не берем с собой на сервер

set :user,     "deployer"  # наш пользователь
set :group,    "staff"  # его группа
set :password, "XXXX"  # пароль от пользователя deployer
set :use_sudo, false  # в debian нам это не надо, в ubuntu может и включить прийдется

set :deploy_to,       "/home/#{user}/#{application}"  # наша папка куда мы размещаем /home/deployer/project_name
set :bundle_dir,      File.join(fetch(:shared_path), 'gems')
role :web,            deploy_server  # наши сервера, так как он один, то на всех
role :app,            deploy_server
role :db,             deploy_server, :primary => true

ssh_options[:forward_agent] = true # тут "магия" по поводу если вы используете ключи и делаете sudo
set :ssh_options, {:forward_agent => true}
set :normalize_asset_timestamps, false

set :rvm_ruby_string, "1.9.3@projects_gemset"  # здесь версия нашего ruby и созданного gemset'а, может его и надо будет создать
set :rvm_type, :system
set :rails_env, 'production'

set :rake,            "rvm use #{rvm_ruby_string} do bundle exec rake --trace"
set :bundle_cmd,      "rvm use #{rvm_ruby_string} do bundle"

task :set_current_release, :roles => :app do
  set :current_release, latest_release
end

set :unicorn_conf,    "#{deploy_to}/current/config/unicorn.rb"
set :unicorn_pid,     "#{deploy_to}/shared/tmp/unicorn.pid"  # путь к нашему unicorn инстансу
set :unicorn_start_cmd, "(cd #{deploy_to}/current; rvm use #{rvm_ruby_string} do bundle exec unicorn_rails -Dc #{unicorn_conf})"  # команда для его запуска

# описания наших задачек для загрузки данных в базу и рестартов unicorn сервера
namespace :deploy do
  desc "reload the database with seed data"
  task :seed do
    run "cd #{deploy_to}/current; rvm use #{rvm_ruby_string} do bundle exec rake db:seed RAILS_ENV=production"
  end

  desc "Start application"
  task :start, :roles => :app do
    run unicorn_start_cmd
  end

  desc "Stop application"
  task :stop, :roles => :app do
    run "[ -f #{unicorn_pid} ] && kill -QUIT `cat #{unicorn_pid}`"
  end

  desc "Restart Application"
  task :restart, :roles => :app do
    run "[ -f #{unicorn_pid} ] && kill -USR2 `cat #{unicorn_pid}` || #{unicorn_start_cmd}"
  end
end


Теперь нам надо еще настроить сам Unicorn сервер, потому просто кладем в config/unicorn.rb файл подобного вида, тоже немного комметариев, все остальное можно найти в сети и тут unicorn.bogomips.org/Unicorn/Configurator.html
ENV['RAILS_ENV'] = 'production'
worker_processes 1  # количество воркер процессов, я люблю делать их по кол-ву ядер например
preload_app true
user('deployer','staff')  # здесь указываем пользователя и группу его
timeout 30 # таймаут работы приложения

@app = "/home/deployer/project_name/current"  # путь к нашему размещенному приложению, разумеется project_name меняем на ваш везде
@shared = "/home/deployer/project_name/shared"  # путь к shared папке

listen "#{@shared}/tmp/unicorn.socket"  # путь где будет лежать открытый Unicorn
working_directory "#{@app}"
pid "#{@shared}/tmp/unicorn.pid"  # ключ инстанса нашего запущенного сервера
stderr_path "#{@shared}/log/unicorn.stderr.log"  # пути к логам unicorn'а
stdout_path "#{@shared}/log/unicorn.stdout.log"

GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end

after_fork do |server, worker|
  Rails.cache.reset if Rails.cache.respond_to? :reset
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end


Разумеется конфигурируем нашу базу данных в файле config/database.yml чтобы production соответствовала нашему серверу. На этом все с конфигурированием, теперь делаем разворачивание:
cap deploy:setup

команда создаст нам первоначальную структуру проекта на сервере, но не хватает одной папки tmp, чтобы создать ее и проставить права надо в консоли сервера набрать:

mkdir /home/deployer/project_name/shared/tmp && chmod 0775 /home/deployer/project_name/shared/tmp && chown deployer:staff /home/deployer/project_name/shared/tmp


в консоли, чтобы создать структуру приложения на нашем сервере и дальше:
cap deploy
cap deploy:migrate
cap deploy:restart

разворачиваем приложение, 2-ой строкой запускаем миграции в БД и перезапуск нашего веб-сервера.

Проверить запущенно ли приложение или нет на сервере можно в консоли набрав ps axu | grep unicorn.

Дело за малым, настроить NGINX и открыть доступ к только, что размещенному серверу из вне.

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.