Как разработчики, мы обычно заботимся о разработке любого приложения. Мы мало думаем о части развертывания, так как считаем, что это ответственность SysAdmins. Но часто у нас нет выделенного SysAdmin, поэтому мы должны надеть шапку SysAdmin и добиться цели. Существует много вариантов развертывания вашего Rails-приложения. Сегодня я расскажу, как развернуть приложение Rails в Amazon Web Services (AWS) с помощью Capistrano.
Мы будем использовать стек Puma + Nginx + PostgreSQL. Puma будет сервером приложений, Nginx — обратным прокси, а PostgreSQL — сервером базы данных. Этот стек также можно использовать в MRI Ruby или JRuby. Большинство шагов остаются одинаковыми для обоих рубинов, но я выделю, где они также различаются.
Если у вас есть существующее приложение, вы можете пропустить следующий раздел и перейти непосредственно к следующему разделу.
Пример приложения Rails
Давайте создадим пример приложения Rails с моделью контакта и CRUD. Приложение использует Rails 4.2 и PostgreSQL:
rails new contactbook -d postgresql
После того, как приложение сгенерировано, создайте модель контактов и CRUD:
cd contactbook
rails g scaffold Contact name:string address:string city:string phone:string email:string
Установите имя пользователя и пароль вашей базы данных в config/database.yml
rake db:create && rake db:migrate
Давайте проверим, как это работает:
rails s
Направьте ваш любимый браузер на http: // localhost: 3000 / contacts и проверьте, все ли работает правильно.
Настройка Puma & Capistrano
Теперь мы настроим приложение для развертывания. Как упоминалось ранее, Puma является сервером приложений, а Capistrano — нашим инструментом развертывания. Capistrano обеспечивает интеграцию для Puma и RVM, поэтому добавьте эти драгоценные камни в Gemfile. Мы также будем использовать гем figaro для сохранения конфигурации приложения, такой как пароль рабочей базы данных и секретный ключ:
gem 'figaro'
gem 'puma'
group :development do
gem 'capistrano'
gem 'capistrano3-puma'
gem 'capistrano-rails', require: false
gem 'capistrano-bundler', require: false
gem 'capistrano-rvm'
end
Установите драгоценные камни через упаковщик:
bundle install
Пришло время настроить Capistrano, сначала сгенерировав файл конфигурации, следующим образом:
cap install STAGES=production
Это создаст файлы конфигурации для Capistrano по адресу config / deploy.rb и config / deploy / production.rb . deploy.rb — это основной файл конфигурации, а production.rb содержит параметры среды, такие как IP-адрес сервера, имя пользователя и т. д.
Добавьте следующие строки в Capfile , который находится в корне приложения. По завершении Capfile включает задачи интеграции RVM, Rails и Puma:
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/rails/assets' # for asset handling add
require 'capistrano/rails/migrations' # for running migrations
require 'capistrano/puma'
Теперь отредактируйте файл deploy.rb следующим образом:
lock '3.4.0'
set :application, 'contactbook'
set :repo_url, '[email protected]:devdatta/contactbook.git' # Edit this to match your repository
set :branch, :master
set :deploy_to, '/home/deploy/contactbook'
set :pty, true
set :linked_files, %w{config/database.yml config/application.yml}
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/uploads}
set :keep_releases, 5
set :rvm_type, :user
set :rvm_ruby_version, 'jruby-1.7.19' # Edit this if you are using MRI Ruby
set :puma_rackup, -> { File.join(current_path, 'config.ru') }
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock" #accept array for multi-bind
set :puma_conf, "#{shared_path}/puma.rb"
set :puma_access_log, "#{shared_path}/log/puma_error.log"
set :puma_error_log, "#{shared_path}/log/puma_access.log"
set :puma_role, :app
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production'))
set :puma_threads, [0, 8]
set :puma_workers, 0
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :puma_preload_app, false
Мы отредактируем production.rb позже, так как мы еще не знаем IP сервера и другие детали.
Кроме того, создайте config / application.yml, чтобы сохранить любые специфичные для среды параметры в среде разработки. Этот файл используется гемом figaro для загрузки настроек в переменные окружения. Мы создадим тот же файл и на рабочем сервере.
Следует помнить одну вещь: исключить config / database.yml и config / application.yml из репозитория Git. Оба файла содержат конфиденциальные данные, которые не следует проверять в системе контроля версий для очевидных проблем безопасности.
Создание экземпляра EC2
С приложением, настроенным и готовым к развертыванию, пришло время запустить новый экземпляр EC2. Войдите в консоль управления EC2 (очевидно, вам необходимо зарегистрировать учетную запись AWS):
Нажмите «Запустить экземпляр»:
Выберите образ машины Amazon (AMI). Мы будем использовать «Ubuntu Server 14.04 LTS»:
Выберите тип экземпляра согласно вашему требованию. Я выбираю «t2.micro», потому что это бесплатно / дешево. Для реального производственного сервера вы бы хотели пойти больше. Нажмите «Далее: Настройка подробностей экземпляра», чтобы продолжить.
Настройки по умолчанию подходят для нашего урока. Нажмите «Далее: Добавить хранилище».
Объем хранилища по умолчанию составляет 8 ГБ. Отрегулируйте согласно вашему требованию к месту. Нажмите «Далее: экземпляр тега»
Введите имя экземпляра. Нажмите «Далее: Настроить группу безопасности».
Нажмите «Добавить правило». Выберите «HTTP» из «Типа». Это необходимо для того, чтобы сервер nginx был доступен из Интернета. Нажмите «Просмотр и запуск»
Проверьте правильность всех настроек. Нажмите «Запустить»
Выберите или создайте пару ключей для подключения к экземпляру. У вас должен быть закрытый ключ на вашем локальном ящике, чтобы подключиться к экземпляру EC2. Ключ должен находиться в вашем каталоге ~ / .ssh . Установите флажок «Я подтверждаю это…» и нажмите «Запустить экземпляр». Подождите, пока экземпляр запустится.
Экземпляр должен быть в рабочем состоянии. Выберите экземпляр и нажмите «Подключиться».
Запишите «публичный IP-адрес» (на скриншоте 52.2.139.74. Ваш будет другим). Нам понадобится это для подключения к серверу.
Настройте сервер
Теперь мы подготовили сервер, и пришло время настроить некоторые основные вещи. Прежде всего, SSH на сервер с нашим выбранным закрытым ключом. Замените «Devdatta.pem» полным путем к вашему личному ключу:
ssh -i "Devdatta.pem" [email protected]
Вы вошли на совершенно новый сервер. Сначала обновите существующие пакеты:
sudo apt-get update && sudo apt-get -y upgrade
Создайте пользователя с именем deploy
sudo useradd -d /home/deploy -m deploy
Это создаст пользовательское deploy
Приложение будет развернуто в этом каталоге. Установите пароль для пользователя deploy
sudo passwd deploy
Введите пароль и подтвердите его. Этот пароль потребуется RVM для установки Ruby. Также добавьте пользователя deploy
Запустите sudo visudo
deploy ALL=(ALL:ALL) ALL
Сохраните файл и выйдите.
Поскольку мы будем использовать GitHub для размещения нашего Git-репозитория, пользователю deploy
Таким образом, мы сейчас сгенерируем пару ключей для этого пользователя:
su - deploy
ssh-keygen
Не устанавливайте ключевую фразу для ключа, так как она будет использоваться в качестве ключа развертывания.
cat .ssh/id_rsa.pub
Скопируйте вывод и установите его как ключ развертывания на GitHub .
Capistrano подключится к серверу через ssh для развертывания в качестве учетной записи deploy
Поскольку AWS допускает только аутентификацию с открытым ключом, скопируйте открытый ключ с локального компьютера в учетную запись пользователя deploy
В большинстве случаев открытый ключ — это ваш ключ ~/.ssh/id_rsa.pub
На сервере:
nano .ssh/authorized_keys
Вставьте ваш локальный открытый ключ в файл. Сохранить и выйти.
Git требуется для автоматического развертывания через Capistrano, поэтому установите Git на сервер:
sudo apt-get install git
Если вы используете JRuby, установите виртуальную машину Java (JVM):
sudo apt-get install openjdk-7-jdk
Установка Nginx
Сначала установите Nginx, который является нашим обратным прокси:
sudo apt-get install nginx
Теперь настройте сайт по умолчанию как наше требование. Откройте файл конфигурации сайта:
sudo nano /etc/nginx/sites-available/default
Закомментируйте существующий контент и вставьте следующее в файл.
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/contactbook/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/contactbook/public;
try_files $uri/index.html $uri @app;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_pass http://app;
}
location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
gzip_static on;
expires max;
add_header Cache-Control public;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Сохраните файл и выйдите. Мы настроили nginx в качестве обратного прокси-сервера для перенаправления HTTP-запросов на сервер приложений Puma через сокет UNIX. Мы пока не будем перезапускать nginx, так как приложение готово. Давайте установим PostgreSQL сейчас.
Установка PostgreSQL
sudo apt-get install postgresql postgresql-contrib libpq-dev
После установки postgreSQL создайте производственную базу данных и ее пользователя:
sudo -u postgres createuser -s contactbook
Установите пароль пользователя из консоли psql
sudo -u postgres psql
После входа в консоль измените пароль:
postgres=# \password contactbook
Введите новый пароль и подтвердите его. Выйдите из консоли с помощью \q
Пришло время создать базу данных для нашего приложения:
sudo -u postgres createdb -O contactbook contactbook_production
Установка RVM & Ruby
Мы будем использовать RVM для установки желаемой версии Ruby:
su - deploy
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable
Это установит RVM в домашний каталог пользователя deploy
Выйдите из системы и войдите снова, чтобы загрузить RVM в оболочку пользователя deploy
Выйдите из системы с помощью Ctrl + D и войдите снова с помощью su - deploy
Теперь установите Ruby:
Для использования MRI Ruby — rvm install ruby
Для JRuby — rvm install jruby
После установки Ruby перейдите на установленную версию:
rvm use jruby
ИЛИ
rvm use ruby
Установить пакет:
gem install bundler --no-ri --no-rdoc
Создайте каталоги и файлы, необходимые для Capistrano. Мы создадим файлы database.yml и application.yml для хранения настроек базы данных и других специфических данных среды:
mkdir contactbook
mkdir -p contactbook/shared/config
nano contactbook/shared/config/database.yml
Вставьте следующее в database.yml :
production:
adapter: postgresql
encoding: unicode
database: contactbook_production
username: contactbook
password: contactbook
host: localhost
port: 5432
После этого создайте application.yml
nano contactbook/shared/config/application.yml
и добавьте следующее:
SECRET_KEY_BASE: "8a2ff74119cb2b8f14a85dd6e213fa24d8540fc34dcaa7ef8a35c246ae452bfa8702767d19086461ac911e1435481c22663fbd65c97f21f6a91b3fce7687ce63"
Измените секрет на новый, используя команду rake secret
Хорошо, мы почти закончили с сервером. Вернитесь на свой локальный компьютер, чтобы начать развертывание с Capistrano. Отредактируйте файл config / deploy / production.rb, чтобы установить IP-адрес сервера. Откройте файл и вставьте следующее в файл. Измените IP-адрес в соответствии с IP-адресом вашего сервера:
server '52.2.139.74', user: 'deploy', roles: %w{web app db}
Теперь давайте начнем развертывание с использованием Capistrano:
cap production deploy
Поскольку это первое развертывание, Capistrano создаст все необходимые каталоги и файлы на сервере, что может занять некоторое время. Capistrano развернет приложение, перенесет базу данных и запустит сервер приложений Puma. Теперь войдите на сервер и перезапустите nginx, чтобы перезагрузить нашу новую конфигурацию:
sudo service nginx restart
Откройте браузер и укажите его / контактам . Приложение должно работать правильно.
Заворачивать
Сегодня мы узнали, как развернуть приложение Rails на AWS с Capistrano. Наше приложение, будучи простым, не использует дополнительные сервисы, такие как фоновые задания, поэтому сегодня я не рассматривал это. Но установка и настройка таких сервисов могут потребоваться для сложных приложений. Но это на другой день.
Ваши комментарии и мнения всегда приветствуются.