ХостингРазворачиваем rails-приложение правильным и удобным методом

В этой статье я расскажу как проще и удобнее всего разворачивать приложения на ruby on rails на нашем хостинге. Используя эту инструкцию вы сэкономите время и легко обнаружите ошибки, которые могут возникать при развертывании Rails-приложений. Так же будет информация о самых частых проблемах и о том, как их избежать. Описанный метод так же подходит и для Rack-приложений, с некоторыми оговорками и незначительными изменениями в конфигурационных файлах.

Сервер приложений.

На серверах locum.ru для Rails-приложений по умолчанию используется unicorn. По запросу можно создать проект, который будет использовать Phusion Passenger, но обычно это не требуется. Unicorn зарекомендовал себя как быстрый и очень гибкий в использовании сервер для rails и rack.

Определяем нужную версию Rails.

Итак, мы решили разместить приложение на ruby on rails на сервере locum.ru. Первое что нам нужно знать — версию Ruby On Rails, которую использует наше приложение. Если это Rails ветки 2.3 и версия выше 2.3.5 — дополнительные действия не нужны. Можно сразу переходить к следующему шагу. Приложение на Rails 2.3.5 и старше скорее всего не получится запустить на Unicorn, из-за несовместимости этих версий с нужной версией Rack. Стоит отметить, что для большинства приложений будет достаточно просто поменять версию фреймворка на 2.3.6 в config/environment.rb, чтобы все заработало на unicorn, например с популярным issue-трекером Redmine это легко решает проблему запуска.

Если наше приложение использует rails 3.X, первым делом следует войти по ssh на сервер и установить соответствующий gem. Для этого нужно выполнить команду:

gem install rails --user-install --no-rdoc --no-ri

Если хочется использовать Bundler и устанавливать gem вне стандартного пути «~/.gem»,  то нужно установить хотя бы rack версии 1.2 в стандартный путь для gem аналогичной командой:

gem install raсk --user-install --no-rdoc --no-ri

Дело в том, что unicorn при старте запускается вне bundle, поэтому он будет использовать rack 1.1, и не сможет запустить приложение, требующее более новую версию rack, так же как и не сможет заменить в процесс работы уже активированную версию rack на более новую. Это является особенностью работы rack и часто приводит к ошибкам, если не помнить о ней.

Создание проекта из панели управления.

Теперь нужно зайти в панель управления и создать проект для нашего приложения. Заходим в раздел «проекты», создаем новый проект с типом Ruby On Rails. Если планируется использовать отличную от MySQL базу данных, то отключаем пункт «создать базу данных», так как по умолчанию создается база именно этого типа.

Размещение кода на сервере.

Создание проекта занимает некоторое время, но после этого у вас на сервер в директории projects появится директория с именем проекта, а в ней стандартная структура каталогов для Сapistrano.  Удобнее всего использовать именно capistrano для загрузки кода на сервер. Это стандартное средство, которое позволяет легко обновлять версию кода, перезапускать сервер приложений, а так же многое другое. Пример конфигурационного файла, адаптированного для использования с нашим хостингом и unicorn можно скачать по следующей ссылке: http://locum.ru/examples/deploy.rb

Заменив в примере нужные значения вы сможете легко загрузить ваш проект на сервер и перезапустить unicorn командой «cap deploy».

Если не хочется использовать capistrano — это не проблема, можно обойтись и без  нее. Структура директорий такова:

имя проекта/
   current -> текущий каталог для unicorn, является символической ссылкой на одну из версий в релизах
   releases/ -> директория с версиям приложения
       initial_release/ -> созданное по умолчанию приложение

Вам нужно разместить код вашего приложения в директории внутри releases, имя выберите произвольно, а затем изменить ссылку current, чтобы она указывала на директорию с вашим приложением, вместо initial_release, сделать это можно командой ln -sf по ssh.

Типичной ошибкой является удаление директории initial_release или всех файлов в ней.  Дело в том, что у нас unicorn использует очень удобный метод перезапуска. Когда приходит команда на перезагрузку сервера, запускается новый экземпляр unicorn, загружается код и затем, если все в порядке — новый экземпляр замещает предыдущий, а старый завершается. Сам процесс немного сложнее, но полное описание работы unicorn выходит за рамки этой статьи. Так как старый процесс был запущен в то время, когда ссылка current указывала на каталог initial_release, то и лог пишется там. Если новый экземпляр unicorn не сможет запуститься, то информацию об ошибке следует искать в файле log/unicorn.stderr.log именно по старому пути. Если эти файлы удалить, unicorn будет все еще пытаться писать по открытому заранее дескриптору, но прочитать мы эти данные уже не сможем. Если директория initial_release вам чем-то мешает, то вы всегда сможете удалить ее позже, после того как эти файлы уже перестанут использоваться.

После того, как файлы размещены и ссылка current изменена следует зайти в подробности проекта в панели управления хостингом и нажать кнопку «перезагрузить сервер».  В случае использования capistrano, сервер будет перезапущен автоматически. Через минуту вы можете зайти на URL вашего проекта и увидеть свое приложение в работе.

Распространенные ошибки, где их искать и как избежать.

Опыт показывает, что самой распространенной проблемой при размещении rails-приложений на нашем хостинге является  нехватка того или иного gem или же нужной его версии. Этого можно избежать, если описывать все, необходимые для работы кода gem в environment.rb и выполнять rake gems:install перед перезагрузкой unicorn с новым кодом. Так же можно использовать bundler и выполнять bundle install. Имейте ввиду, что команда bundle по умолчанию будет пытаться установить gem в системные директории, что конечно же не удастся сделать без root-доступа. Поэтому не забывайте всегда использовать ключ —path с указанием пути, куда вы хотите устанавливать локальные gem. Можно делать это, например, в директорию «~/.gem».

Так же, некоторые пользователи банально забывают внести нужные настройки для базы данных в database.yml. Не забывайте, что на нашем хостинге все проекты запускаются в режиме ‘production’, а значит и настройки нужно вносить в соответствующей секции database.yml

Что делать, если после перезагрузки кода unicorn на сайте проекта ничего не поменялось? Это значит, что новый экземпляр unicorn не смог запуститься по какой-то причине. Для выяснения причины нужно посмотреть последние строки файла log/unicorn.stderr.log в той директории, где запущена версия unicorn, которая осталась работать. При загрузке нового приложения это будет releases/initial_release.

Еще одна частая ошибка, это попытка зайти на домен, созданный для проекта сразу после появления его в панели управления. Дело в том, что для перезагрузки конфигурации DNS-сервера требуется некоторое время, потому лучше подождать несколько минут. В противном случае можно оказаться в неприятной ситуации. DNS сервер вашего провайдера может кэшировать ответы на запросы, если вы зайдете слишком рано и получите ответ, что такого домена нет, и это попадет в кэш, может получиться, что после того, как наш DNS сервер уже начнет сообщать IP-адрес этого домена, вы  все еще будете получать ошибочный ответ из кэша.

Коллектив Locum.ru желает успеха всем нашим пользователям в разработке и размещении проектов.

  1. Спасибо за статью! Есть вопрос по поводу Unicorn.

    Уже третий проект на Локуме перевели на Unicorn. Деплой проходит отлично, но почему-то задача deploy:restart выполняется как success, но сервер не перезагружается. Для того, чтобы перезагрузить сервер приходится выполнять отдельно cap deploy:stop, а затем cap deploy:start.

    Конфигурацию берём из вашего конфига:

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

  2. unicorn_pid правильно установлен? Попробуйте выполнить команду на сервере руками с подставлением правильных значений, тогда будет скорее всего понятна причина ошибки.

  3. у вас ссылка на deeploy.rb корявая.

    Побольше бы в статье технических подробностей.

  4. Спасибо, Владимир. Ссылку исправили.Более подробно технически возможно будет в следующих статьях.

  5. Анатолий:

    сделайте deploy.rb со стратегией «set :deploy_via, :copy».
    чтоб без левого внешнего репозитория.
    а то я не могу из локального репозитория загрузить.

  6. Анатолий, вы можете легко отредактировать deploy.rb и внести в него нужные изменения, все равно без правок не обходится — имя проекта и пользователя нужно вписывать. Это пример конфигурации, а не готовое решение для 100% случаев.

  7. Владимир Шакиров:

    Очень мало тех подробностей.
    По данной статье сложно развернуть приложение на хостинге

  8. Владимир Шакиров:

    У меня возникли несколько вопросов. По Capistrano я установить так и не смог, поэтому пытаюсь воспользоваться вторым вариантом (загрузка напрямую на сервер).

    Подскажите пожалуйста, как изменить ссылку current?
    Точнее что написать после ln -sf

    Так же я пытаюсь проинсталировать bundle install в свой проект, но у меня не получется попасть в директорию. Пишет следующее

    hosting_xxx@lithium:~/projects/yyy$ cd list
    -bash: cd: list: Слишком много уровней символьных ссылок

    Заранее спасибо!

  9. Сергей:

    Спасибо вам огромное. Информации в статье вполне достаточно. Очень дешево и быстро. Я рад :)

  10. eJay:

    Присоединяюсь! Сделайте пожалуйста deploy.rb со стратегией «set :deploy_via, :copy». Заранее спасибо.

  11. Неплохо было бы написать откуда брать файлы /etc/unicorn/project.login.rb и /var/run/unicorn/project.login.pid ? У меня нет доступа для их создания.

  12. Андрей, pid-файл будет создан самим unicorn, если его нет — unicorn не запущен. А конфиг в /etc/unicorn создается нашей панелью управления при создании проекта. Вам не нужно будет его создавать или редактировать.

  13. Alexey Kad:

    Сегодня обновился до 3.0.4. В этот раз все установилось без вмешательства техподдержки (во время установки 3.0.3 не хватало процессорного времени для выполнения команды). Супер!

  14. Yerlan:

    В статье мало тех.деталей(
    При деплое приложения, вылетает такая ошибка:
    [lithium.locum.ru] executing command
    ** [lithium.locum.ru :: err] Host key verification failed.
    ** [lithium.locum.ru :: err] fatal: The remote end hung up unexpectedly
    что-то с ключами видимо, репозиторий у меня на гитхабе.

  15. vi:

    Спасибо, все получилось.
    Использовал capistrano.

  16. […] Рекомендую почитать хорошую статью о правильном деплое приложения на Rails. Лучшая благодарность автору – ваши комментарии и […]

  17. Alexey Kad:

    Был твит, что на локуме можно развернуть locomotive cms.
    Хотелось бы статью. По примеру родной http://www.locomotivecms.com/support/installation/engine только для локума.

  18. Всем привет. Подскажите как Git настроить на Locum? в упор не могу понять как с Github подружить

  19. Спасибо. Добавлю, мне для запуска rails приложений понадобилось поправить файл Gemfile — раскомментировать unicorn. Хочу спросить: меняю код, а изменения не применяются, приходится перезагружать из панели управления, так задумано?

  20. zed911:

    в production окружении изменения динамически не применяются, это только для разработки. RTFM короче =)

  21. Павел:

    В последнее время невозможно стало задеплоиться.
    Если заходишь по ssh получаешь:
    -bash: fork: retry: Ресурс временно недоступен
    -bash: fork: retry: Ресурс временно недоступен
    -bash: fork: retry: Ресурс временно недоступен
    -bash: fork: retry: Ресурс временно недоступен
    -bash: fork: Ресурс временно недоступен

    А капистрано при таких условиях труда не работает.

  22. Максим:

    Подскажите кто нибудь как побороть ошибку
    failed: «sh -c ‘[ -f /var/run/unicorn/erevan.hosting_maxstbn.pid ] && kill -USR2 `cat /var/run/unicorn/erevan.hosting_maxstbn.pid` || /var/lib/gems/1.8/bin/unicorn_rails -Dc /etc/unicorn/erevan.hosting_maxstbn.rb'» on lithium.locum.ru

  23. Павел, это значит, что превышен лимит одновременно запущенных процессов по тарифу. Можете попросить поддержку остановить некоторые из них, скорее всего там есть несколько ненужных, или перейти на следующий тариф.
    Максим, это значит, что unicorn почему-то не стартовал, нужно смотреть log/unicorn.*.log, там будет видно причину.

  24. Илья:

    Доброго времени суток,с чем может быть связана подобная ошибка:
    ** [hydrogen.locum.ru :: err] Host key verification failed.
    ** [hydrogen.locum.ru :: err] fatal: The remote end hung up unexpectedly