自動でデプロイさせて負担を軽減する
デプロイの作業は非常に手間です。
いちいちその作業をすれば、随分な時間が取られてしまいます。
煩わしいので、自動化させましょう
これまでのデプロイまでの流れを振り返る
ここまでデプロイするための作業をしましたが、簡単に流れを振り返りましょう
- git push
- git pull
- SSH接続
- アセットコンパイル
- Unicorn再起動
この一連の流れをすれば、デプロイが完了されます。
なお、この一連の流れをまだしたことがない、自信がないという人は
詳しく解説している下記の記事を閲覧してください。
EC2インスタンスを立ち上げるまでの記事はシリーズ化しているので、こちらをどうぞ
独学ではじめてAWSのEC2にデプロイする方法①~⑩(インスタンスの作成)
capistranoとは
この一連のデプロイ作業を自動化させる、様々のツールの一つにcapistranoがあります。
capistranoを利用することでサーバーにログインしなくても"" コマンド一つで ””デプロイできちゃうのですから、非常に楽です。
一度Capistranoにデプロイが成功すれば、簡略してエラーなしにデプロイができます。
Capistranoの導入
Gemのインストール
ローカルのwebappにCapistranoのgemを追加しましょう
group :development, :test do
gem 'capistrano'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano3-unicorn'
end
続いて、インストールします
$ bundle install
gemがインストールできたところで、Capistranoの下記のコマンドを実施
$ bundle exec cap install
するとファイルが作成されます。
railsルート
├─ Capfile
├─ config
│ ├─ deploy
│ │ ├─production.rb
│ │ └─staging.rb
│ └─deploy.rb
└─ lib
└─capistrano
└─tasks
これらのファイル説明は作業しながら学びましょう
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を編集
production.rbですが2つファイルがあります
❌ config/environment/production.rb
⭕️ config/deploy/production.rb
今回作業はするのはconfig/deploy/production.rbです
実際に開くと下記の画面が出ます。
このファイルを下記を追記しましょう!(元が全部コメントアウトなので、どこでも可能)
server '18.○○○.○○.○○○(Elastic IP)', user: 'ec2-user', roles: %w{app db web}
deploy.rbを編集
下記を追加します
# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '○.○○.○(Capistranoのバージョン)'
# Capistranoのログの表示に利用する
set :application, '○○○(自身のアプリケーション名)'
set :deploy_to, '/var/○○○(アプリを入れているディレクトリ)/○○○(アプリ名)'
# どのリポジトリからアプリを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のバージョン)' #カリキュラム通りに進めた場合、2.5.1か2.3.1です
# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
keys: ['~/.ssh/○○○○○.pem(ローカル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
貼り付けたテンプレートの一部を修正しましょう
lock '<Capistranoのバージョン>'
Capistranoのバージョンを確認するために、Gemfile.lockを開きましょう
capistrano (3.11.1)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
これでCapistranoのバージョンが(3.11.1)とわかりました。
ではdeploy.rbを修正しましょう
lock '3.11.1'
rubyのバージョン確認
set :rbenv_ruby, '○.○.○(rubyのバージョン)'
ターミナルで下記を実行しましょう
$ ruby -v
> ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]
○○○のところは、アプリ名などを入れる必要があるので、穴埋めしてください
set :application, '○○○(自身のアプリケーション名)'
set :repo_url, 'git@github.com:○○○(Githubのユーザー名)/○○○(レポジトリ名.git'
keys: ['~/.ssh/○○○○○.pem(ローカルPCのEC2インスタンスのSSH鍵(pem)へのパス 例:~/.ssh/key_pem.pem))']
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"
上記のunicorn.rbの記述を下記に変更
# ../が一つ増えている
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の設定ファイルを編集
ec2-user@ip-17-242-2-2 アプリ名$ sudo vim /etc/nginx/conf.d/rails.conf
そして、capistranoに合わせた参照先に変更します。(詳細はコメントアウトで解説しています。)
upstream app_server {
# sharedの中を参照するよう変更(/shared/tmp/sockets/unicorn.sock;)
server unix:/var/○○○(アプリをまとめているディレクトリ)/○○○○○(アプリケーション名)/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name 18.○○○.○○(Elastic IP);
# currentの中を参照するよう変更(/current/public;)
root /var/○○○(アプリをまとめているディレクトリ)/○○○○○(アプリケーション名)/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
# currentの中を参照するよう変更(/current/public;)
root /var/○○○/○○○○○○(アプリケーション名)/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の設定を変更したら、忘れずに再読込・再起動
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx reload
[ec2-user@ip-172-31-25-189 ~]$ sudo service nginx restart
MySQLの起動を確認
[ec2-user@ip-172-31-25-189 ~]$ sudo service mysqld restart
unicornのプロセスをkillしよう
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicorn
一番上のunicorn_rails masterをkillしたいので、下記を実施
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill 17877
ローカルでの修正を全てmasterにpushしてください
自動デプロイの実施
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy
エラーが発生する場合
ディレクトリ `/var/www' を作成できません: 許可がありません
mkdir stdout: Nothing written
mkdir stderr: mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません
mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません
ヒヤリング:手動デプロイはできていたか?
・YES:Capistranoの設定の問題(ここまで進めている以上、できているはず)
・NO:もう一度手動デプロイを確認する必要があるかもしれません。
設定の見直し
rails.confとdeploy.rbのパスの確認をしてください。
var/www/アプリ名で設定しているか?
・ディレクトリはwwwの場合、入力間違いがないか???
・ディレクトリは"wwwでない"場合、capistranoのデフォルト設定を変更する必要がある。
EC2でのアプリの保存場所が『 var/www/アプリ名 』でない場合、、
[参考](https://capistranorb.com/documentation/getting-started/configuration/)
deplory.rbに下記を追加してください。
set :deploy_to, '/var/○○○/アプリ名'
capistranoのデフォルト設定では、/var/www/アプリ名が設定されているため、これを変更する必要がある。
そのオプション設定がset :deploy_to, '/var/○○○/アプリ名'である。
Master.keyがないエラー( Missing encryption key to decrypt file with. Ask your team for your master key and write it to )
このエラーが表示されたということは、『 本番環境にあるmaster.keyをうまく読み込めていない 』ことを意味します。
rake stdout: Nothing written
rake stderr: Missing encryption key to decrypt file with. Ask your team for your master key and write it to /var/○○○(アプリを格納しているディレクトリ名)/○○○(アプリ名)/releases/20200121124714/config/master.key or put it in the ENV['RAILS_MASTER_KEY'].
なので現状として可能性は二つです。
- master.keyを作成していない。
- master.keyを作成する場所が間違っている。
ここまで作業を進めている人は,master.keyを作成しているはずです。
>つまり、master.keyの作成場所をまちがている可能性が高いです。
# 誤解が生まれやすいmaster.keyの作成場所
✖︎ アプリ名>config>master.key
○ アプリ名>shared>config>master.key
おそらく、上記のようにmaster.keyの作成場所に誤りがある可能性が高いです。
ですから、
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ cd shared
[ec2-user@ip-172-31-23-189 shared ]$ cd config
[ec2-user@ip-172-31-23-189 config ]$ ls
>ここでmaster.keyがない場合、 master.keyを作成してください。
master.keyを作成する場合、、、
アプリ名 $ vi config/master.key
>master.keyを中身がわかります。
>間違っても編集しないようにしましょう
ローカル環境のmaster.keyをコピーしたら、EC2にmaster.keyを作成しましょう
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ cd shared/config
[ec2-user@ip-172-31-23-189 config ]$ vi master.key
>編集画面が出るので
>ローカルのmaster.keyをコピペします。
>:wpで保存しましょう
master.keyを読み込ませるために、deploy.rbに
下記を追加してください
set :linked_files, fetch(:linked_files, []).push("config/master.key")
再度自動デプロイしましょう
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy
今度はうまくいくはずです。
最後に
未経験からエンジニアになるための最強ノウハウを共有しています。
これで知り合い全員エンジニアになったので、未経験からエンジニアになりたい方は
参考にしてみてください
https://note.com/gyu_outputs/n/nfd80b9dab981