すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 Capistranoを使ってデプロイを自動化しよう

ぴっかちゃん
ぴっかちゃん

Capistranoというgemは面倒なデプロイ作業を自動化してくれるツールです。面倒なデプロイ作業もコマンド一つで行うことができます。

AWSのEC2を使ってデプロイをする際、非常に多くの手順を踏む必要があります。
それをコマンド1つで行ってくれるのが自動デプロイツールです。

その自動デプロイツールで人気があるのはCapistranoというgemです。

capistrano

この記事ではAWSのEC2でNginxとUnicornを使った際のCapistranoの導入方法について解説していきます。
※EC2でのデプロイ方法については【Rails】 AWSのEC2でRailsのアプリをデプロイしようの記事を参照ください

自動デプロイツールとは

デプロイの記事でも解説した通り、AWSのEC2サービスでRailsアプリのデプロイを行うには下記の手順が必要です。

  1. EC2インスタンスにSSH接続をする
  2. EC2インスタンスにpullする
  3. アセットのコンパイルをする
  4. Unicornの再起動をする

といったようにデプロイの度にEC2インスタンスに接続したり、Unicornの再起動をしたりと、とても面倒です。
これをローカルのターミナルのたった一つのコマンドで行ってくれるのが自動デプロイツールです。
導入することによって簡単になることはもちろん、コマンドの打ち間違いによるミスなどもなくなるので、デプロイ自体がとても信憑性のあるものになります。

Capistranoを導入しよう

この章では自動デプロイツールの一種であるCapistrano(カピストラーノ)というgemの導入方法を解説していきます。

gemをインストールしよう

Capistranoを導入するにはgemをインストールする必要があります。
Gemfileの開発環境の部分を下記のように編集します。

Gemfile | gemの追加
1
2
3
4
5
6
7
group :development do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

Capistrano以外にもgemを追加しています。

gem名 役割
capistrano-rbenv Capistranoでrbenvでインストールしたrubyを使用可能にする
capistrano-bundler Capistranoで自動でbundle installを可能にする
capistrano-rails Capistranoでマイグレーションやアセットのコンパイルを可能にする
capistrano3-unicorn CapistranoでUnicornの再起動などを可能にする

そしてbundle installコマンドでインストールします。
次に下記のコマンドを実行します。

ローカルのターミナル | cap のインストール
1
2
3
4
5
6
7
8
9
% bundle exec cap install
# ファイルが作成される
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

このコマンドを実行することにより下記のようなファイルが作成されます。

1
2
3
4
5
6
7
8
9
10
アプリケーション名
  ├── Capfile
  ├── config
  │   ├── deploy
  │   │     ├── production.rb
  │   │     └── staging.rb
  │   └── deploy.rb
  └── lib
        └── capistrano
                └── tasks

次に作成されたファイルの編集を行います。

Capfileを編集しよう

Capfileはインストールしたgemの中からCapistranoで読み込むgemを指定するファイルです。

デフォルトだと下記のようになっています。

Capfile | 中身の確認
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
# Load DSL and set up stages
require "capistrano/setup"

# Include default deployment tasks
require "capistrano/deploy"

# Load the SCM plugin appropriate to your project:
#
# require "capistrano/scm/hg"
# install_plugin Capistrano::SCM::Hg
# or
# require "capistrano/scm/svn"
# install_plugin Capistrano::SCM::Svn
# or
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

# Include tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
#   https://github.com/capistrano/rvm
#   https://github.com/capistrano/rbenv
#   https://github.com/capistrano/chruby
#   https://github.com/capistrano/bundler
#   https://github.com/capistrano/rails
#   https://github.com/capistrano/passenger
#
# require "capistrano/rvm"
# require "capistrano/rbenv"
# require "capistrano/chruby"
# require "capistrano/bundler"
# require "capistrano/rails/assets"
# require "capistrano/rails/migrations"
# require "capistrano/passenger"

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

呼び出すgemを指定するため、Capfileを下記のように全て書き換えましょう。

Capfile | Capfileの編集
1
2
3
4
5
6
7
8
9
10
require "capistrano/setup"
require "capistrano/deploy"
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano3/unicorn"
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

deploy.rbを編集しよう

次はconfigフォルダに作成されたdeploy.rbを編集します。
このファイルはデプロイ時に行われるタスクを設定するファイルです。

デフォルトだと下記のように記述されています。

config/deploy.rb | 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
# config valid for current version and patch releases of Capistrano
lock "~> 3.16.0"

set :application, "my_app_name"
set :repo_url, "git@example.com:me/my_repo.git"

# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp

# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, "/var/www/my_app_name"

# Default value for :format is :airbrussh.
# set :format, :airbrussh

# You can configure the Airbrussh format using :format_options.
# These are the defaults.
# set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto

# Default value for :pty is false
# set :pty, true

# Default value for :linked_files is []
# append :linked_files, "config/database.yml"

# Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"

# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }

# Default value for local_user is ENV['USER']
# set :local_user, -> { `git config user.name`.chomp }

# Default value for keep_releases is 5
# set :keep_releases, 5

# Uncomment the following to require manually verifying the host key before first deploy.
# set :ssh_options, verify_host_key: :secure

これを参考に編集していきます。
デフォルトの記述を下記のように全て書き換えましょう。
2、5、6、14、22行目の部分はご自身のものに差し替えてください。

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
# Capistranoのバージョンを指定(初期から記入済み)
lock 'Capistranoのバージョン'
# アプリケーションの指定
set :application, 'レポジトリ名'
set :repo_url, 'git@github.com:Githubのユーザー名/レポジトリ名.git'
# sharedディレクトリに入れるファイルを指定 append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle", "public/system", "public/uploads" # SSH接続設定 set :ssh_options, { auth_methods: ['publickey'],
keys: ['~/.ssh/プライベートキーの名前.pem']
} # 保存しておく世代の設定 set :keep_releases, 5 # rbenvの設定 set :rbenv_type, :user
set :rbenv_ruby, 'アプリで使用しているrubyのバージョン'
# ここからUnicornの設定 # Unicornのプロセスの指定 set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" } # Unicornの設定ファイルの指定 set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" } # Unicornを再起動するための記述 after 'deploy:publishing', 'deploy:restart' namespace :deploy do task :restart do invoke 'unicorn:restart' end end

Capistranoのバージョンがわからない場合はGemfile.lockで調べましょう。

差し替える例は下記の通りです。
(例)
Capistranoのバージョン: 3.16.0
レポジトリ名: pikawaka
Githubのユーザー名: miyagima
プライベートキーの名前: pikawaka
アプリで使用しているrubyのバージョン: 2.6.5

config/deploy.rb | デプロイ設定の例
1
2
3
4
5
6
7
8
lock "3.16.0"

set :application, 'pikawaka'
set :repo_url,  'git@github.com:miyagima/pikawaka.git'

  keys: ['~/.ssh/pikawaka.pem'] 

set :rbenv_ruby, '2.6.5'

production.rbを編集しよう

configフォルダ内に作成されたdeployフォルダ内には本番環境でのデプロイ設定をするproduction.rbとステージング環境でのデプロイ設定をするstaging.rbという2つのファイルが作成されています。
こちらは環境別に設定するファイルになります。
今回は本番環境のデプロイ設定を行うのでproduction.rbを編集します。

config/deploy/production.rb | デプロイ設定
1
server 'Elastic IPアドレス', user: 'ec2-user', roles: %w{app db web}

上のElastic IPアドレスの部分はご自身のものを入力してください。

(例)Elastic IPアドレスが「12.345.67.89」だった場合

config/deploy/production.rb | デプロイ設定
1
server '12.345.67.89', user: 'ec2-user', roles: %w{app db web}

ディレクトリ構成を把握しよう

先ほどdeploy.rbの記述内に「sharedディレクトリに入れるファイルを指定」というのがありました。
「sharedディレクトリ」とはCapistranoの自動デプロイ時に本番環境のディレクトリに新しく自動で追加されるディレクトリの1つです。
自動で作成されるディレクトリはこれを含めて3つあるので確認しておきましょう。

ディレクトリ名 役割
current 現在デプロイされている内容が保管されている
releases 過去にデプロイした内容が保管されている
shared バージョンに関係なく参照される内容が保管されている

自動デプロイ作業によりディレクトリ構成が変化するので、それに応じて変更するファイルがあります。

Nginxの設定を編集しよう

まずはNginxの設定ファイルを編集します。
EC2インスタンスに接続し、EC2のターミナルで下記のコマンドを実行し、rails.confファイルを編集モードにしましょう。

EC2ターミナル | rails.confの編集
1
[ec2-user@ip-172-12-34-5 ~]$ sudo vim /etc/nginx/conf.d/rails.conf

ファイルの中身が表示されたらiキーを押してINSERTモードにします。
そして下記のように3行目と10行目のコードを編集しましょう。
※記述内容はAWSのEC2でRailsのアプリをデプロイしようの記事内のコードを参照しています

/etc/nginx/conf.d/rails.conf | rails_confの編集
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 unicorn {
// 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; } 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://unicorn; } try_files $uri/index.html $uri @unicorn; error_page 500 502 503 504 /500.html; }

フォルダ構成の部分を編集したらescキーを押してINSERTモードから抜けましょう。
その後、:wqと入力しenterキーを押して編集モードから抜けます。

unicorn.rbを編集しよう

次にUnicornの設定ファイルであるunicorn.rbを編集します。

config/unicorn.rb | 設定ファイルの編集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# rootパスのディレクトリを指定(「../」が先頭に追加)
root_path = File.expand_path('../../../', __FILE__)
# アプリケーションサーバの性能を決定する worker_processes 2 # アプリケーションの設置されているディレクトリを指定(current内に変更)
working_directory "#{root_path}/current"
# プロセスIDの保存先を指定(shared内に変更)
pid "#{root_path}/shared/tmp/pids/unicorn.pid"
# ポート番号を指定(shared内に変更)
listen "#{root_path}/shared/tmp/sockets/unicorn.sock"
# エラーのログを記録するファイルを指定(shared内に変更)
stderr_path "#{root_path}/shared/log/unicorn.stderr.log"
# 通常のログを記録するファイルを指定(shared内に変更)
stdout_path "#{root_path}/shared/log/unicorn.stdout.log"
# 以下略

これで準備は完了です。
今までの編集を反映させるため、commitしGitHubへpushしましょう。

自動デプロイをしてみよう

この章では実際に自動デプロイをする流れを解説していきます。
設定ファイルを色々と変更したので、Nginxの再起動をします。

EC2ターミナル | Nginxの再起動
1
2
[ec2-user@ip-172-12-34-5 ~]$ sudo systemctl reload nginx
[ec2-user@ip-172-12-34-5 ~]$ sudo systemctl restart nginx

またデータベースが起動しているか念のため確認しておきます。

EC2ターミナル | データベースの確認
1
2
3
4
5
6
7
8
[ec2-user@ip-172-12-34-5 ~]$ sudo systemctl status mariadb
● mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled)
   Active: active (running) since 土 2021-05-29 23:31:10 UTC; 4 days ago
 Main PID: 6514 (mysqld_safe)
   CGroup: /system.slice/mariadb.service
           ├─6514 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
           └─6680 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log...

「Active: active (running)」となっていれば問題ありません。
起動していなかったら下記のコマンドでデータベースを起動しましょう。

EC2ターミナル | データベースの確認
1
[ec2-user@ip-172-12-34-5 ~]$ sudo systemctl start mariadb

自動デプロイコマンドを実行しよう

それでは自動デプロイを行います。
ローカルのターミナルから下記のコマンドを実行します。

ローカルのターミナル | 自動デプロイの実行
1
% bundle exec cap production deploy

するとデプロイが始まり下のようなログが出力されます。

ローカルのターミナル | ログの確認
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
00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 ec2-user@18.123.148.102 0.087s
      Uploading /tmp/git-ssh-c28cb931191aa47e7611.sh 100.0%
      02 chmod 700 /tmp/git-ssh-c28cb932291aa47e7611.sh
    ✔ 02 ec2-user@18.123.148.102 0.099s
00:00 git:check
      01 git ls-remote git@github.com:********/******.git HEAD
      01 84fdc5b49f9ab467d2834a6eded8bdaa11ec284b   HEAD
    ✔ 01 ec2-user@18.123.148.102 2.136s
00:02 deploy:check:directories
      01 mkdir -p /var/www/*******/shared /var/www/*******/releases
    ✔ 01 ec2-user@18.123.148.102 0.084s
00:02 deploy:check:linked_dirs
      01 mkdir -p /var/www/*******/shared/log /var/www/******/shared/tmp/pids /var/www/******/shared/tmp/cache /va…
    ✔ 01 ec2-user@18.123.148.102 0.089s
00:02 git:clone
      The repository mirror is at /var/www/******/repo
00:03 git:update
      01 git remote set-url origin git@github.com:*******/*******.git
    ✔ 01 ec2-user@18.123.148.102 0.093s
      02 git remote update --prune
      02 Fetching origin
      02 From github.com:******/******
      02    161aad2..84fdc5b  master     -> master
    ✔ 02 ec2-user@18.123.148.102 2.351s
(以下省略)

途中でエラーが発生していなければ自動デプロイ完了です。
エラーが発生している場合はもう一度編集し忘れている箇所がないか、commitやpushのし忘れはないか確認してみましょう。

その後、ブラウザで更新内容が反映されているか確認をし、反映されていれば自動デプロイ完了です。

今後も下記の手順で自動デプロイを行います。

  1. アプリを編集する
  2. commitをする
  3. ブランチを切っている場合はmergeする
  4. GitHubのmasterブランチへpushする
  5. ローカルのターミナルで自動デプロイコマンドを打つ

エラーを解決しよう

ブラウザで確認したところ、「We're sorry, but somethig went wrong.」のエラーが出てしまっている場合はlogファイルからエラーの原因を確認しましょう。
自動デプロイ後はcurrentディレクトリにログが格納されています。

EC2ターミナル | ログの確認
1
[ec2-user@ip-172-12-34-5 レポジトリ名]$ tail -f current/log/production.log

こちらのコマンドでエラーがどこで起こっているか確認をしましょう。

自動デプロイツールを使うとこのように簡単にデプロイができるようになります。

コマンドの打ち間違いや作業のし忘れなどがなくなるメリットもあるので、ぜひ導入してみてはいかがでしょうか。他にもコードの品質を上げる方法などより現場レベルに近い知識を身につけたい方は、こちらの書籍で学ぶと深く理解することができます。

この記事のまとめ

  • 自動デプロイツールとは面倒なデプロイ作業を簡単に行うことができるツール
  • Capistranoは自動デプロイツールの一つ
  • 導入するとコマンド1つでデプロイが完了