AWS Capistranoで自動デプロイ
まず普通にローカルでインストールして設定してく
Gemfile
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
色々ファイルができるので説明してく
1アプリケーション直下にあるCapfile
Capistranoの機能を提供するコードはいくつかのライブラリ(Gem)に分かれています。そのため、Capistranoを動かすにはいくつかのライブラリを読み込む必要があります。Capfileは、Capistrano関連のライブラリのうちどれを読み込むかを指定できます。
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 }
require により引数としておかれた文字列が指すディレクトリが読み込まれ、その中にデプロイに際して必要な動作が一通り記述されています。
2 config/deploy/以下のproduction.rbとstaging.rb
どっちもデプロイする環境別の設定を記述するファイル
今回は本番環境だけ、つまりproduction.rbだけ弄る
config/deploy/production.rb
server '<用意した自分のElastic IP>', user: 'ec2-user', roles: %w{app db web}
サーバホスト名、AWSサーバーへのログインユーザー名、サーバーロール、SSHの設定、その他のサーバーに基づく任意の設定を記述していくらしい。
3.config/以下のdeploy.rb
こっちはproduction,stagingどちらの環境にも当てはまる設定を記述する
アプリケーション名、gitのレポジトリ 、利用するSCM、タスク、それぞれのタスクで実行するコマンドなんかを設定する。
とりあえずこの通りしとこうか
t# config valid only for current version of Capistrano
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<自分のアプリのCapistranoのバージョン>'
# Capistranoのログの表示に利用する
set :application, '<自身のアプリケーション名>'
# どのリポジトリからアプリを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のバージョン>'
# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
keys: ['<ローカル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
補足
set:名前, 値;でDSLみたいに定義してる。fetch名前で値が取り出せる。
desc 'hoge'とかtask: hoge do みたいなのはrequireしたものに加えてcap deploy時に実行されるタスクを追加してる感じ
自動デプロイ後のアプリのディレクトリ構成。(本番環境の方)
アプリケーション直下に三つディレクトリ増えているので把握しとく
1releasesディレクトリ
デプロイされたアプリを指定した回数分だけ保存しとくとこ。今回は5回分保存してる(set:keep_releasesのとこ)。ここに前のバージョンが入ってるから一つ前に戻す、みたいなことができる。
2currentディレクトリ
releasesの中で一番新しい物がコピーされて入ってる。要は現在のデプロイの内容だと思っていい。
3 sharedディレクトリ
バージョンが変わっても共通で参照されるディレクトリが入ってる。
log,public,tmp,vendorディレクトリとかが入ってる
Capistranoに合わせてunicorn.rbを修正
capistranoでのデプロイ後は、アプリケーションディレクトリ直下にあるcurrentディクトりが動くことにあるので、実際に動くディレクトリを意味するworking_directoryの部分を修正する。またログやpidの指定をshared以下にするなどの修正をする。
具体的には
もともとの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
# 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"
|
そもそもapp_path = File.expand_path('../../../', __FILE__)って何やねん
https://qiita.com/msy-naka/items/43c70e470a63f82b53a7
https://maeharin.hatenablog.com/entry/20130104/p1
このあたりの記事に参考にして、多分
app_pathがちゃんと(多分)EC2インスタンのトップからのパス返すように../で上の階層に戻ってる感じなんだけど、動くのがcurrentの予定だから一個深くなったので、動く予定のファイルからちゃんと一番上(/var/www/アプリ/current)まで戻った上で__FILE__でファイル名までのパスを返すようにしてるって感じだと思う。この感じだと__FILE__って絶対パス返すもんなのかと思ったけど、必ずしも絶対パスとは限らんらしい。とりあえずこのくらいの理解でいいか。
Nginxの方もCapistranoに合わせて修正する
こちらも今までvar/www/以下のアプリと連携していたものを、
var/www/アプリ/currentとかshared
と連携するように設定する
webサーバーはEC2のサーバー内にあるのでそちらで
$ sudo vim /etc/nginx/conf.d/rails.conf
開くと現状
rails.conf
upstream app_server { server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock; } server { listen 80; server_name <Elastic IPを記入>; # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく client_max_body_size 2g; root /var/www/<アプリケーション名>/public; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control 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; }
こんな感じになってるだろうから、ガッツリ修正して
upstream app_server { # sharedの中を参照するよう変更 server unix:/var/www/<自分のアプリケーション名>/shared/tmp/sockets/unicorn.sock; } server { listen 80; server_name <自分のElastic IPを記入>; # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく client_max_body_size 2g; # currentの中を参照するよう変更 root /var/www/<自分のアプリケーション名>/current/public; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; # currentの中を参照するよう変更 root /var/www/<自分のアプリケーション名>/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; }
こんな感じに 修正
設定したら再起動
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
|
[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
ローカルのターミナルい戻り以下のコマンドで自動デプロイを実行する
(もちろんローカルの変更はpushしてある状態で)
アプリケーションのディレクトリで実行する $ bundle exec cap production deploy
エラーが表示されずに終われば成功。ただし、メモリ不足で落ちることもあるみたいなのでもう一度試す。それでもおかしければ不備がないか確認する。
(デフォでsshのエラー出るから注意↓サーバー起動時にssh鍵の設定がおかしくなるっぽい)
https://qiita.com/aoitrain/items/90036ec9c24f0566711e
最後にブラウザからIPアドレスにアクセスして確認終了
以降はローカルの変更をリモートリポジトリにpushした後に
bundle exec cap production deploy
で反映される
追記予定
まだ必要かわからんけどとりあえず
https://qiita.com/tanakayo/items/9d5e091ce5ce52bbdc9a
とか読むことになりそうな気がする