前回までにNginxというWebサーバを本番環境に導入しました
今回はCapistranoというgemを使って自動デプロイできるようにします
まず、ローカルのアプリにgemを導入します
Gemfile
group :development, :test do
gem 'capistrano'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano3-unicorn'
end
gemを記述したらターミナルで以下を実行します
ローカル
bundle install
bundle exec cap install
Capistranoをインストールするとファイルがいくつか自動生成されるので必要なファイルをそれぞれ編集します
まずCapfileです
Capfile
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
次にproduction.rbです
config/deploy/production.rb
server '<用意したElastic IP>', user: 'ec2-user', roles: %w{app db web}
次にdeploy.rbです
config/deploy.rb
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<Capistranoのバージョン>'
# Capistranoのログの表示に利用する
set :application, '<自身のアプリケーション名>'
# どのリポジトリからアプリをpullするかを指定する
set :repo_url, 'git@github.com:<Githubのユーザー名>/<レポジトリ名>.git'
# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :rbenv_type, :user
set :rbenv_ruby, '<このアプリで使用しているrubyのバージョン>'
# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
keys: ['<ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス(例:~/.ssh/key_pem.pem)>']
# プロセス番号を記載したファイルの場所
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
# Unicornの設定ファイルの場所
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5
# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
task :restart do
invoke 'unicorn:restart'
end
end
続いてunicorn.rbの編集を行います
Capistrano導入によってディレクトリ構造が変わるためです。
config/unicorn.rb
app_path = File.expand_path('../../', __FILE__)
worker_processes 1
working_directory app_path
pid "#{app_path}/tmp/pids/unicorn.pid"
listen "#{app_path}/tmp/sockets/unicorn.sock"
stderr_path "#{app_path}/log/unicorn.stderr.log"
stdout_path "#{app_path}/log/unicorn.stdout.log"
↓↓↓↓↓↓↓ 以下のように変更 ↓↓↓↓↓↓
# ../が一つ増えている
app_path = File.expand_path('../../../', __FILE__)
worker_processes 1
# currentを指定
working_directory "#{app_path}/current"
# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
ローカルの変更は完了です
本番のNginxも変更の必要があります
以下のようにごっそり変更します
$ sudo vim /etc/nginx/conf.d/rails.conf
EC2インスタンス
upstream app_server {
# sharedの中を参照するよう変更
server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name <Elastic IPを記入>;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
# currentの中を参照するよう変更
root /var/www/<アプリケーション名>/current/public;
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
error_page 500 502 503 504 /500.html;
}
自動デプロイの準備が完了しました
あとは本番環境のNginx、MySQLを再スタートさせて、Unicornをkillさせます
$ sudo service nginx reload
$ sudo service nginx restart
$ sudo service mysqld restart
$ ps aux | grep unicorn
$ kill <確認したunicorn rails masterのPID>
ローカル
$ bundle exec cap production deploy
これで自動デプロイが完了です