
Приклад деплоя app на Ruby On Rails
В даній замітці розглядається приклад деплою проетку під назвою tools на VPS-сервер Ubuntu 14.04, код проекту знаходиться на git-сервері bitbucket.org у приватному репозиторію. Використовуємо Ruby 2.3.1 та Ruby On Rails 4.2
Підготовка VPS-серверу
Створюємо користувача deployer, в цілях деплоя нашого app
1 |
adduser deployer |
Додаємо його в sudo (/etc/sudoers)
1 |
deployer ALL=(ALL:ALL) NOPASSWD:ALL |
Оновлюємо встановлений софт та інсталюємо curl та nodejs
1 2 3 |
sudo apt-get update sudo apt-get upgrade sudo apt-get install curl nodejs |
Якщо виникає warning на кшталт
1 2 3 4 5 6 7 |
perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LANG = "en_US.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). |
виконуємо наступні дії:
1 2 |
sudo locale-gen en_US.UTF-8 sudo dpkg-reconfigure locales |
якщо у warning'у фігурує 'uk_UA.UTF-8', то відповідно
1 2 |
sudo locale-gen uk_UA.UTF-8 sudo dpkg-reconfigure locales |
(у мене ця помилка виникала в Ubuntu 14.04. Без її усунення будемо мати проблеми при інсталяції Postgres)
Інсталюємо RVM
1 2 3 4 5 6 |
command curl -sSL https://rvm.io/mpapis.asc | gpg --import - curl -L get.rvm.io | bash -s stable source ~/.rvm/scripts/rvm rvm install 2.3.1 rvm use 2.3.1 --default rvm rubygems current |
Інсталюємо Postgres
1 |
sudo apt-get install postgresql postgresql-contrib libpq-dev |
Створюємо базу даних та користувача
1 |
sudo -u postgres psql |
1 2 3 |
create user deployer with password 'password'; alter role deployer superuser createrole createdb replication; create database MYAPP_production owner deployer; |
Інсталюємо Git
1 |
sudo apt-get install git-core |
Інсталюємо Bundler
1 |
gem install bundler |
Інсталюємо Nginx та редагуємо конфігураційни файл default-хосту
1 |
sudo apt-get install nginx |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
upstream backend { server unix:/home/deployer/applications/tools/shared/tmp/sockets/puma.sock; } server { listen 80; root /home/deployer/applications/tools/current/public; try_files $uri/index.html $uri.html $uri @tools; location ~ ^/assets/ { gzip_static on; expires max; add_header Cache-Control public; } location @tools { proxy_pass http://backend; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; } } |
Генерація ssh ключів
Оскільки користувачу deployer потрібний доступ до git-серверу а репозиторій проекту у нас приватний, ми генеруємо ssh-key
1 |
ssh-keygen -t rsa -C "<your@mail>" |
та додаємо ключ
1 |
cat ~/.ssh/id_rsa.pub |
Підготовка проекту на локальній машині для деплоя
Для деплоя проекту, нам потрібний ssh-доступ з докальної машини на VPS-сервер, для цього добавимо ssh-key на сервер deploy'я
1 |
ssh-copy-id deployer@<deploy-server.hostname> |
якщо у config/secrets.yml ми маємо
1 2 |
production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> |
тоді генеруємо токен
1 |
bundle exec rake secret |
та вставляємо його замість <%= ENV[“SECRET_KEY_BASE”] %>
Якщо проект в стадії розробки, варто буде в config/environments/production.rb задати
1 |
config.consider_all_requests_local = true |
щоб бачити реальні помилки замість сторінки із "we're sorry"
Capistrano
В нашому локальному проекті добавимо наступні gem'и (в Gemfile)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
group :development do # Джем, який добавляє специфічні для Rails таски, такі як прогон міграцій і компіляція ассетів gem 'capistrano-rails' gem 'capistrano-rails-console' # Джем, який добавляє можливість bundle до capistrano gem 'capistrano-bundler' # Добалвення підтримки RVM (менеджера версій для Ruby) gem 'capistrano-rvm' # Інтеграція пуми и капістрано gem 'capistrano3-puma' gem 'capistrano-linked-files' end group :production do # Puma - це Ruby/Rack сервер, який буде отримувати запроси від Nginx та перенаправляти їх у Rails gem 'puma' end |
Виконуємо інсталяцію нових gem'ів та capistrano
1 2 |
bundle install cap install |
В результаті у нас з'являться наступні два нові файли
config/deploy.rb
config/deploy/production.rb
Конфігурація config/deploy.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# Назва проекту set :application, 'tools' # Шляз до tools репозиторія set :repo_url, 'git@bitbucket.org:saviokmua/tools.gtu.net.ua.git' # Вітка за змовчанням set :branch, 'master' # Директорія для деплоя set :deploy_to, '/home/deployer/applications/tools' set :default_stage, 'production' set :log_level, :info # Файли та директорії (між деплоями), об'єкти яких немає в проеті потрібно забрати set :linked_files, %w{config/database.yml} set :linked_dirs, %w{tmp/pids tmp/cache tmp/sockets vendor/bundle public/uploads} # А це рекомендують добавити для проектів, які використовують ActiveRecord set :puma_init_active_record, true namespace :deploy do desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do # Your restart mechanism here, for example: # execute :touch, release_path.join('tmp/restart.txt') end end after :restart, :clear_cache do on roles(:web), in: :groups, limit: 3, wait: 10 do # Here we can do anything such as: # within release_path do # execute :rake, 'cache:clear' # end end task :seed do on roles(:all) do within release_path do with rails_env: fetch(:rails_env) do execute :rake, "db:seed" end end end end task :precompile do on roles(:all) do within release_path do with rails_env: fetch(:rails_env) do execute :rake, "assets:precompile --trace" end end end end task :setup do before "deploy:migrate", :create_db invoke :deploy end task :create_db do on roles(:all) do within release_path do with rails_env: fetch(:rails_env) do execute :rake, "db:create" end end end end end after :finishing, 'deploy:cleanup' # Uploading both linked_files and dirs before :finishing, 'linked_files:upload' # Uploading only linked_files before :finishing, 'linked_files:upload_files' # Uploading only dirs before :finishing, 'linked_files:upload_dirs' end |
Конфігурація config/deploy/production.rb, полягає лише у втсавці ip-адресу vps-серверу
1 |
server '<ip>', user: 'deployer', roles: %w{web app db} |
Якщо ви не захотіли по якійсь причині використовувати ключі для доступу до VPS-серверу, ми можете прописати ssh-параметри доступу в цьому файлі
1 2 3 4 5 6 7 |
set :ssh_options, { forward_agent: false, auth_methods: %w(password), password: '<your_password>', user: 'deployer', } |
Конфігурація Capfile
1 2 3 4 5 6 7 8 9 10 11 |
require "capistrano/setup" require "capistrano/deploy" require 'capistrano/rvm' require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/puma' require 'capistrano/puma/workers' # if you want to control the workers (in cluster mode) require 'capistrano/puma/nginx' # if you want to upload a nginx site templat require 'capistrano/linked_files' Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r } |
Виконуємо deploy!
1 2 |
bundle exec cap production linked_files:upload_files cap production deploy |