AWSに再デプロイするのは大変な作業で、変更内容が反映されないというエラーも起きやすいので、コマンド1つでデプロイ出来る方法は無いか探しました。
#これまでのデプロイ
- git push
- git pull
- SSH接続
- アセットコンパイル
- Unicorn再起動
とても面倒ですよね・・・
Capistrano を使い,1コマンドで Rails アプリを AWS EC2 にデプロイできる状態にしようと思いました。
capistranoを利用することでサーバーにログインしなくてもコマンド一つで再デプロイ可能な為、非常に楽です。
一度Capistranoにデプロイが成功すれば、簡略してエラーなしにデプロイができます。
#Capistranoの導入
Gemfile
group :development do
# 略
# ***** 以下を追加 *****
gem "capistrano", "~> 3.10", require: false
gem "capistrano-rails", "~> 1.6", require: false
gem 'capistrano-rbenv', '~> 2.2'
gem 'capistrano-rbenv-vars', '~> 0.1'
gem 'capistrano3-puma'
# ***** 以上を追加 *****
end
ローカル環境のターミナル
bundle install
bundle exec cap install STAGES=production
Capfile の # require "capistrano/passenger" の下に以下を追加
Capfile
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Systemd
install_plugin Capistrano::Puma::Nginx
デプロイの設定ファイルを修正・追記しましょう。
「アプリ名」「GitHubリポジトリURL」は各自のものに置き換えて下さい。
「GitHubリポジトリURL」は HTTPS でなく SSH のURLをコピペして下さい。
config/deploy.rb
# config valid for current version and patch releases of Capistrano
lock "~> 3.14.1"
# ***** 以下を修正 *****
set :application, "アプリ名"
set :repo_url, "GitHubのリポジトリURL"
set :rbenv_ruby, File.read('.ruby-version').strip
set :branch, ENV['BRANCH'] || "master"
# Nginxの設定ファイル名と置き場所を修正
set :nginx_config_name, "#{fetch(:application)}.conf"
set :nginx_sites_enabled_path, "/etc/nginx/conf.d"
append :linked_files, "config/master.key"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "node_modules"
# ***** 以上を追加 *****
production.rb の一番上に,EC2サーバーにログインするユーザー名、サーバーのロールを記述して下さい。
「ElatsticIP」「アプリ名」「ユーザー名」は各自のものに置き換えて下さい。
config/deploy/production.rb
server "ElatsticIP", user: "ユーザー名", roles: %w{app db web}
set :ssh_options, {
keys: %w(~/.ssh/アプリ名.pem),
forward_agent: true,
auth_methods: %w(publickey),
}
##master.key の配置と Rails アプリのデプロイ
準備が整いましたので,Railsアプリのデプロイを行います。
初回の実行では master.key がないためデプロイに失敗しますが, master.key を配置するために必要なディレクトリが生成されます。
デプロイ失敗後に scp コマンドで master.key をサーバー側に追加し,再度実行すればデプロイに成功します。
ローカル環境のターミナル
# Railsアプリのルートディレクトリに移動してから
bundle exec cap production deploy
# 「ERROR linked file /var/www/アプリ名/shared/config/master.key does not exist on ElasticIP」が出ればOK
scp config/master.key $APP_NAME:/var/www/$APP_NAME/shared/config
bundle exec cap production puma:config
bundle exec cap production puma:systemd:config puma:systemd:enable
【注意】 ブランチが master でない場合は, BRANCH=HEAD を付けた bundle exec cap production deploy BRANCH=HEAD を実行して下さい.
最後のコマンドで, /etc/systemd/system/puma_アプリ名_production.service が作成されます。このファイルの $HOME を実際のパスに変更しないとエラーが出るため,修正して下さい。
サーバー環境のターミナル
echo $HOME
# ここで表示されるパス「/home/ユーザー名」をコピー
cd /etc/systemd/system/
vi puma_${APP_NAME}_production.service
# 開かれたファイルの ExecStart=$HOME の $HOME を先ほどコピーしたものに置き換えて保存終了です!
sudo systemctl daemon-reload
sudo systemctl enable puma_${APP_NAME}_production.service
これで準備が完了です。再度デプロイしてみます!
ローカル環境のターミナル
bundle exec cap production deploy
【備考】ここでデプロイに失敗した場合は,まずエラー文を確認します。いろいろなケースがありますが,アプリで使用されている gem 次第では,先に依存関係にあるプラグインを EC2 にインストールしておく必要があります。
##Nginx の設定
Nginx 用の設定ファイルを追加するため,先に必要なディレクトリをサーバー側で作成しておきます。
サーバー環境のターミナル
cd /etc/nginx
sudo mkdir sites-available}
ローカル環境 のターミナルで,Railsアプリのルートディレクトリまで移動した後,以下を実行します。
これで Nginx 用の設定が生成されます。
ローカル環境のターミナル
# Railsアプリのルートディレクトリに移動してから
bundle exec cap production puma:nginx_config
これで,サーバー側の /etc/nginx/conf.d に設定ファイル アプリ名.conf が入ります。
Nginx を再起動します。
サーバー環境のターミナル(/etc/nginx)
sudo service nginx restart
ブラウザのアドレスバーに Elastic IP を入力してアクセスし, スーパーリロード して下さい。(ショートカットキーは command + shift + r)
アプリが表示されればOKです。
【補足】アプリが表示されない場合は,以下↓を試して下さい.
ローカル環境のターミナルから curl -I ElasticIP を実行したとき,最初に HTTP/1.1 301 Moved Permanently が出力される場合
config/environments/production.rb の config.force_ssl = true をコメントアウトして下さい。