yujiroのプログラミング

勉強内容をアウトプットし、サボらないようにする為のブログ

<DAY100>復習アウトプット用 Capistranoを利用した自動デプロイ

\ Follow me!! /

学習状況

●学習日数 100日

●学習時間(本日)8時間

●累計学習時間 450時間

●一日あたりの平均学習時間 4.5時間

Capistranoの導入

group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

読み込ませてコマンド打ちます。
ファイルを生成させる

bundle install
bundle exec cap install


Capfile
require により、引数としておかれた文字列が指すディレクトリが読み込まれ、
その中にデプロイに際して必要な動作が一通り記述

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 }

config/deploy/production.rb
本番環境に関する記述を追加する。

server '<用意したElastic IP>', user: 'ec2-user', roles: %w{app db web}

ここには、production環境、staging環境どちらにも当てはまる設定を記述することとなります。
具体的には下記のような項目があります。

アプリケーション名
gitのレポジトリ
利用するSCM
タスク
それぞれのタスクで実行するコマンド


config/deploy.rb

# config valid only for current version of Capistrano
lock '<Capistranoのバージョン>'

set :application, '自身のアプリケーション名'
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)へのパス>']  

set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end

unicornも手動設定の時より一段ディレクトリが深くなっているため変更

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

working_directory "#{app_path}/current"
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の設定ファイルも同様に設定変更

location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }
      
 ↓↓↓↓↓↓↓ 以下のように変更 ↓↓↓↓↓↓

location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    root   /var/www/<アプリケーション名>/current/public;
  }

自動デプロイ前の注意

Nginxの設定を変更したら、再起動
自動デプロイを実行する前にunicornのコマンドをkill
全てmasterにpushされていることを確認

sudo service nginx reload
 cd /var/www/<アプリ名>
kill -QUIT `cat tmp/pids/unicorn.pid`  #Unicornの停止

capistranoした場合、本番環境のディレクトリが一段深くなる件にについて

一度Capistranoによる自動デプロイを実行すると、本番環境のアプリケーションのディレクトリが変化します。
Capistranoによるアプリのバックアップなど、複数のディレクトリが作成されます。その中でも特に重要なのが、releases、current、sharedディレクトリです。


f:id:yujiro0320:20190821163756p:plain

releasesディレクト

capistranoを通じてデプロイされたアプリは、releasesというフォルダにひとまとめにされます。
ここに過去分のアプリが残っていることにより、デプロイ時に何か問題が発生しても一つ前のバージョンに戻ったりすることができます。
そして、その過去分の保存数を指定しているのがdeploy.rbのset :keep_releasesの記述となります。今回は5つ、過去のバージョンを保存するよう設定しました。

currentディレクト

releasesフォルダの中で一番新しいものが、自動的にcurrentというフォルダ内にコピーされているような状態になります。
そのため、このcurrent内に入っているアプリの内容が、現在デプロイされている内容ということになります。

sharedディレクト

バージョンが変わっても共通で参照されるディレクトリが格納されるディレクトリです。具体的には、log、public、tmp、vendorディレクトリが格納されます。