Приклад деплою App на Ruby On Rails
В даній замітці розглядається приклад деплою проетку під назвою tools на VPS-сервер Ubuntu 18.04 в каталог /home/deployer/apps/project/, код проекту знаходиться на git-сервері bitbucket.org у приватному репозиторію. Використовуємо Ruby 2.4.0 та Ruby On Rails 5
Підготовка VPS-серверу
Під root’ом:
Для нашого проекту створюємо окремого користувача deployer:
1 |
adduser deployer |
Додаємо його в sudo (/etc/sudoers)
1 |
deployer ALL=(ALL:ALL) NOPASSWD:ALL |
Налаштовуємо часовий пояс
1 |
tzselect |
Задаємо UTF-8 локаль, редагуємо /etc/default/locale до наступного вигляду:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
LANG=uk_UA.UTF-8 LANGUAGE="en_US.UTF-8", LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME=ru_UA.UTF-8 LC_COLLATE="en_US.UTF-8" LC_MONETARY="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_PAPER="en_US.UTF-8" LC_NAME="en_US.UTF-8" LC_ADDRESS="en_US.UTF-8" LC_TELEPHONE="en_US.UTF-8" LC_MEASUREMENT="en_US.UTF-8" LC_IDENTIFICATION="en_US.UTF-8" LC_ALL="en_US.UTF-8" |
У /etc/environment добавляємо наступне:
1 2 |
LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 |
Далі виконаємо наступні команди
1 2 3 |
sudo locale-gen en_US.UTF-8 sudo locale-gen uk_UA.UTF-8 sudo dpkg-reconfigure locales |
Оновлюємо встановлений софт та інсталюємо необхідне ПО
1 2 3 4 |
sudo apt-get update sudo apt-get upgrade sudo apt-get install curl libcurl4 libcurl4-openssl-dev nodejs postgresql postgresql-contrib libpq-dev git mc imagemagick libmagic-dev gnupg2 nginx |
Під юзером deployer:
Інсталюємо RVM
актуальна інструкція на офіційному сайті – https://rvm.io/
на момент написання замітки, порядок був наступний:
1 |
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB |
1 2 |
\curl -sSL https://get.rvm.io | bash -s stable source /home/deployer/.rvm/scripts/rvm |
1 2 3 |
rvm install 2.5.1 rvm use 2.5.1 --default rvm rubygems current |
Створюємо базу даних та користувача
1 |
sudo -u postgres psql |
1 2 3 4 |
create user deployer with password 'password'; alter role deployer superuser createrole createdb replication; create database MYAPP_production owner deployer; \q |
Інсталюємо Passenger + Nginx
актуальна інструкція на оф.сайт, на момент написання замітки, порядок дій наступний:
1 2 3 4 5 6 7 8 9 10 11 |
sudo apt-get install -y dirmngr gnupg sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7 sudo apt-get install -y apt-transport-https ca-certificates <span class="c unselectable"># Add our APT repository</span> sudo sh -c <span class="s1">'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger <span class="debian_codename si">bionic</span> main > /etc/apt/sources.list.d/passenger.list'</span> sudo apt-get update <span class="c unselectable"># Install Passenger + Nginx module</span> sudo apt-get install -y libnginx-mod-http-passenger sudo service nginx restart |
1 |
1 2 |
gem install bundler gem install passenger |
Створюємо файл-конфіг хосту:
1 2 |
nano /etc/nginx/sites-available/mydomain.com |
із наступним змістом
1 2 |
server { </code>listen 80 ; listen [::]:80 ; server_name mydomain.com www.mydomain.com; root /home/deployer/apps/project/current/public; passenger_enabled on; passenger_ruby /home/deployer/.rvm/gems/ruby-2.5.1/wrappers/ruby; passenger_sticky_sessions on; passenger_app_env staging; } |
1 |
1 |
Підключаємо хост та перегружаємо nginx
cd /etc/nginx/sites-enabled/
ln -s /etc/nginx/site-available/mydomain.com
/etc/init.d/nginx restart
Генерація ssh ключів
Оскільки користувачу deployer потрібний доступ до git-серверу а репозиторій проекту у нас приватний, ми генеруємо ssh-key
1 2 |
ssh-keygen |
читаємо ключ та копіюємо його
1 |
cat ~/.ssh/id_rsa.pub |
та додаємо на git-сервер
Підготовка проекту на локальній машині для деплоя
Для деплоя проекту, нам потрібний 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 |
group :development do gem 'capistrano-rails' gem 'capistrano-rails-console' gem 'capistrano-bundler' gem 'capistrano-rvm' gem 'capistrano-passenger' gem 'capistrano-linked-files' 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 |
# Назва проекту set :application, 'tools' # Шляз до tools репозиторія set :repo_url, 'git@bitbucket.org:username/tools' # Вітка за змовчанням set :branch, 'master' # Директорія для деплоя set :deploy_to, '/home/deployer/apps/project' 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' end |
Конфігурація config/deploy/production.rb, полягає лише у втсавці ip-адресу vps-серверу
1 2 |
server '<ip>', user: 'deployer', roles: %w{web app db} </code>set :branch, 'production' set :rails_env, :production set :sidekiq_env, :production |
1 |
Якщо ви не захотіли по якійсь причині використовувати ключі для доступу до 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 |
require "capistrano/setup" require "capistrano/deploy" require 'capistrano/rvm' require 'capistrano/bundler' require 'capistrano/passenger' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' 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 |