7839

雑草魂エンジニアブログ

【Rails】Capistrano で Rails アプリケーションを自動デプロイ(設定編)

Rails アプリケーションを本番、ステージング環境にデプロイする際に、同じ作業を何回もやるのは正直面倒である。今回、Capistrano というデプロイ自動化ツールを使ったので、備忘録を残しておく。

サーバーの環境構築に関しては、【EC2】Rails5 環境構築(Ruby + MySQL5.7 + Node.js + Nginx)を参照してほしい。

Capistrano とは

github.com

Capistrano とは、Ruby 製のデプロイ自動化ツールである。RailsJavaPHPなど、あらゆる言語やフレームワークのプロジェクトのデプロイを自動化することができる。

それぞれのタスクに応じた Capistrano のライブラリが用意されているので、それらを組み合わせたり、独自にタスクを作成することで、デプロイの設定や流れを簡単に作ることができる。

今回は、Railsアプリケーションの自動デプロイの設定について紹介する。デプロイの流れは以下のようになる。

  1. サーバーに SSH 接続する
  2. Capistranoディレクトリ構成を構築する(シンボリックリンクの作成)
  3. git clone
  4. rbenv の動作確認
  5. bundle install(gemインストール)
  6. yarn install(node packageインストール)
  7. yarn build

(今回のRails アプリケーションには、一部 Vue コンポーネントを組み込んでおり、webpack で build する必要がある。)

Capistranoフレームワークでは、デプロイ先のディレクトリ構成は以下のようになる。

Deploy.root
├─ current #公開されているアプリケーション(DocumentRoot)
├─ release #デプロイされたアプリケーションが保存されている
├─ shared  #バージョンが変わっても共通で参照されるファイル
├─ repo    #Capistranoの設定ファイル等
└─ revisions.log #リリースバージョンのログ

・releasesディレクト

Capistrano を通じてデプロイされたアプリケーションは、releasesディレクトリにバージョンごとに纏められる。デプロイ時に問題が発生しても、過去のデータが残っていることで、簡単に一つ前のバージョンに戻ることができる。

・currentディレクト

releasesディレクトリの中で最新のものが、自動的にcurrentディレクトリ内にコピーされる。(正確には、releasesの最新のディレクトリのシンボリックリンクがcurrentディレクトリに作られ、参照している。)DocumentRootには、current/publicを指定する。

$ ls -l
current -> /app/sample-app/releases/20201224144141

・sharedディレクト

バージョンが変わっても共通で参照されるファイルやディレクトリが格納される。具体的には、config の設定ファイル、log、public、tmp ディレクトリが格納される。(これらも、シンボリックリンクが作られて、currentディレクトリの各ファイルから参照される形になる。)

インストール方法

まずは、Rails アプリケーションに Capistrano をインストールする。Gemfile に以下を追記する。

group :development do
  gem 'capistrano', '~> 3.10', require: false
  gem 'capistrano-rails', '~> 1.4', require: false
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-yarn'
end
$ bundle install
# Capistrano の設定ファイルをインストールする
$ bundle exec cap install

上記のコマンドを実行することで、以下のディレクトリが作成される。

Rails.root
├── Capfile #必要なライブラリ、タスクを読み込む
├── config
│ ├─ deploy.rb #共通の設定ファイル
│ └─ deploy
│    ├─ production.rb #本番の設定ファイル
│    └─ staging.rb #ステージングの設定ファイル
└── lib
     └─ capistrano
        └─ tasks #オリジナルのタスクを作成する(Capfileで読み込ませる)

設定方法

設定する流れは、以下になる。

  1. Capfile で必要なライブラリ、タスクを記述する
  2. デプロイの設定を記述する
    • 共通の設定:config/deploy.rb
    • 環境別の設定:config/deply/{stage}.rb

Capfile

# 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/git"
install_plugin Capistrano::SCM::Git
# Include tasks from other gems included in your Gemfile
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/migrations"
require "capistrano/yarn"
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

デプロイの設定

今回は、ステージング環境である staging.rb のみを紹介する。

# Capistranoのバージョンを指定
lock "~> 3.14.1"
# アプリケーションの名前
set :application, "sample-app"
# GitリポジトリのURL
set :repo_url, "git@github.com:sample-app.git"
# サーバー上でのデプロイ先
set :deploy_to, '/app/sample-app' #default: /var/www/my_app_name
# ログの出力設定
set :format, :airbrussh
"log/capistrano.log", color: :auto, truncate: :auto
# sudoを使う場合は、trueにしておく
set :pty, true
# 共有ファイル
append :linked_files, 'config/database.yml', 'config/master.key', 'config/credentials.yml.enc', 'config/puma.rb', '.env'
# 共有フォルダ
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'public/packs'
# 5回分のreleasesを保持する
set :keep_releases, 5
#=======================
# Rails
set :rails_env, 'staging'
set :migration_role, 'db'
# db/migrateに変更がない場合は、Skip migration
set :conditionally_migrate, false
#=======================
# Yarn
set :yarn_flags, "--prefer-offline --no-progress"
set :yarn_roles, :app
set :yarn_env_variables, fetch(:yarn_env_variables, {})
set :yarn_bin, '/opt/nvm/versions/node/v14.15.2/bin/yarn'
desc 'yarn build'
after 'deploy:updated', :build do
  on roles :web do
    within release_path do
      execute :yarn
      execute :yarn, 'build'
    end
  end
end
#=======================
# Rbenv
set :rbenv_type, :system
set :rbenv_custom_path, '/opt/rbenv'
set :rbenv_ruby, '2.6.3'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w(rake gem bundle ruby rails)
set :rbenv_roles, :all
#=======================
# Bundler
set :bundle_roles, :all
set :bundle_binstubs, -> { shared_path.join('bin') }
set :bundle_path, -> { shared_path.join('vendor', 'bundle') }
set :bundle_without, %w(development test).join(' ')
set :bundle_jobs, 8
#=======================
# Server
# Capistranoは実行ユーザの ~/.ssh/config に従うので、configのHostを指定する
server 'sample-staging',
       user: 'ec2-user',
       roles: %w(app web),
       ssh_options: {
         forward_agent: true
       }
#=======================

まとめ

今回は、デプロイ自動化ツールである Capistrano の設定方法に関して、まとめを行った。

次回、実際にデプロイする際に、サーバー側で一部設定をした後に、デプロイを行ったので、その部分に関しても、紹介したい。

それでは、ステキな開発ライフを。

関連記事

serip39.hatenablog.com

serip39.hatenablog.com