LoginSignup
7
14

More than 3 years have passed since last update.

EC2 + RDS + Capistrano + unicorn + nginxでrailsアプリを自動デプロイする【後半】

Last updated at Posted at 2020-03-01

いよいよ本題であるCapistranoを使用したデプロイについて解説していきます。

EC2の事前準備

最初に準備としてEC2内に必要なものをインストールしていきます。

1. rbenv, git,環境変数の設定


[sample_user@ip-10-0-0-79 ~] $  sudo yum -y install git
[sample_user@ip-10-0-0-79 ~] $ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv #rbenv
[sample_user@ip-10-0-0-79 ~] $ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build #ruby-build

[sample_user@ip-10-0-0-79 ~] $ sudo vim .bash_profile

-----------------------------
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

#この2行を追加してpathを通します
-----------------------------

[sample_user@ip-10-0-0-79 ~]  $source ~/.bash_profile  #設定の反映
[sample_user@ip-10-0-0-79 ~] $ rbenv -v #pathが通ったかを確認

環境変数

[sample_user@ip-10-0-0-79 ~] $ sudo vim .bashrc #環境変数の設定


-------------------------------
export sample_variable="sample_sample_sample"
#アプリ内で環境変数を使用している方はここで設定
-------------------------------
[sample_user@ip-10-0-0-79 ~] $ source ~/.bashrc
#設定の反映

2. Ruby(version 2.6.3)

[sample_user@ip-10-0-0-79 ~] $ sudo yum install -y gcc
[sample_user@ip-10-0-0-79 ~] $ sudo yum install -y openssl-devel readline-devel zlib-devel
[sample_user@ip-10-0-0-79 ~] $ rbenv install 2.6.3 #ruby2.6.3をインストール

3. bundler

[sample_user@ip-10-0-0-79 ~] $ rbenv exec gem install bundler
[sample_user@ip-10-0-0-79 ~] $ rbenv rehash

4. mysql

[sample_user@ip-10-0-0-79 ~] $ sudo yum install mysql mysql-server mysql-devel

5. sqlite

[sample_user@ip-10-0-0-79 ~] $ sudo yum install sqlite-devel

6. node.js

[sample_user@ip-10-0-0-79 ~] $ sudo amazon-linux-extras install epel

デプロイ先の作成

Capistranoはgit cloneを通してコードをコピーするため、デプロイ先のディレクトリを作成します。

[sample_user@ip-10-0-0-79 ~] $ sudo mdkir /var/www
[sample_user@ip-10-0-0-79 var] $ sudo chmod 777 www
[sample_user@ip-10-0-0-79 var] $ cd www
[sample_user@ip-10-0-0-79 www] $ mkdir sample_app 
[sample_user@ip-10-0-0-79 www] $ cd sample_app
[sample_user@ip-10-0-0-79 sample_app] $ rbenv local 2.6.3 #バージョンを設定

Git HubのSSh設定

前半でlocalからserverへSSH接続した時と同様に、server側からGit HubへSSH接続ができるよう設定を行います。

[sample_user@ip-10-0-0-79 ~]$ cd .ssh
[sample_user@ip-10-0-0-79 .ssh]$ ssh-keygen -t rsa
Enter file in which to save the key (/home/sample_user/.ssh/id_rsa): sample_git_rsa
#sample_git_rsaという名前で鍵を生成

[sample_user@ip-10-0-0-79 .ssh]$ ls
authorized_keys  sample_git_rsa  sample_git_rsa.pub
[sample_user@ip-10-0-0-79 .ssh]$ cat sample_git_rsa.pub
#中身をコピー

SettingsSSH and GPG keysNew SSH keyでkeyを新規作成し中身を貼り付ける。
スクリーンショット (42).png

次は設定ファイルを作成。


[sample_user@ip-10-0-0-79 .ssh] $ vim config 
-------------------------------------------
Host github
  Hostname github.com
  User git
  IdentityFile ~/.ssh/sample_git_rsa (#先ほど作成した秘密鍵のpath)
-------------------------------------------

最後にserverからGitHubへSSh接続ができているかを確認

[sample_user@ip-10-0-0-79 .ssh] $ sudo chmod 600 config
[sample_user@ip-10-0-0-79 .ssh] $ ssh -T github

#成功
Permanently added the RSA host key for IP address '140.82.114.3' to the list of known hosts.
Hi ichihara-development-github! You've successfully authenticated, but GitHub does not provide shell access.

Nginx

今回はWebサーバーにnginx、アプリケーションサーバーにunicornを使用するのでEC2側でNginxの設定を行います。

Webサーバーとアプリケーションサーバーに関してはこちらの記事が参考になるため、ご一読下さい。

なぜrailsの本番環境ではUnicorn,Nginxを使うのか?  ~ Rack,Unicorn,Nginxの連携について ~【Ruby On Railsでwebサービス運営】

Nginx

[sample_user@ip-10-0-0-79 ~] $ sudo yum install nginx #nginxをインストール
[sample_user@ip-10-0-0-79 ~] $ cd /etc/nginx/conf.d/
[sample_user@ip-10-0-0-79 conf.d] $ sudo vim sample_app.conf #nginxはデフォルト設定で.confファイルを読み込みます

--------------------------------------------
#以下を追加

upstream unicorn {
  server unix:/tmp/unicorn.sock;
}

server {
  listen 80;
  server_name 〇.〇.〇.〇(Elastic IP);

  access_log /var/log/nginx/sample_access.log;
  error_log /var/log/nginx/sample_error.log;
  #エラーログの保存先を指定

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://unicorn;
  }
}
--------------------------------------------

local

それではCapistranoをlocalにインストールし、デプロイの準備を行いましょう。

Gemfile
#以下を追加

gem 'mysql2'

platforms :ruby do
  gem 'unicorn'
end

group :development do
  gem 'capistrano'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
  gem 'capistrano3-unicorn'
end

------------------------------------------

$ bundle install
sample_app
$ 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

bundle exec cap installを実行するとCapistanoの設定ファイルが自動生成されます。

1. Capfileの設定

Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

capistranoを使用できるように読み込みます。

2. config/deploy.rbの設定

config/deploy.rb
lock '3.12.0'

set :application, 'sample_app'
#アプリ名を記載
set :repo_url, 'github:ichihara-development-github/sample_app.git'
#cloneを行うリモートリポジトリを記載
#ただし、configファイルでgithub.com→githubとして置き換えられているので注意

set :rbenv_type, :user
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

set :log_level, :warn

set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')

set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')

set :keep_releases, 3

set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid"

set :unicorn_config_path, -> { File.join(current_path, "config", "unicorn.rb") }

namespace :deploy do
  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do

    end
  end
end

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end

3. config/deploy/production.rbの設定

config/deploy/production.rb

server "〇.〇.〇.〇", user: "sample_user", roles: %w{app db web}
#serverのIPと、ログイン可能なuser名を記載してください


set :ssh_options, {
  keys: %w(~/.ssh/sample_app_key_rsa), #秘密キーのpathを記載
  forward_agent: true,
  auth_methods: %w(publickey),
  port: 22
}


4. unicornの設定(local側)

config配下にunicron.rbを作成します。

config/unicorn.rb


APP_PATH   = "#{File.dirname(__FILE__)}/.." unless defined?(APP_PATH)
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
RAILS_ENV  = ENV['RAILS_ENV'] || 'development'

worker_processes 3

listen "/tmp/unicorn.sock"
pid "tmp/pids/unicorn.pid"

preload_app true

timeout 60
working_directory APP_PATH

# logのpath
stderr_path "#{RAILS_ROOT}/log/unicorn_error.log"
stdout_path "#{RAILS_ROOT}/log/unicorn_access.log"

if GC.respond_to?(:copy_on_write_friendly=)
  GC.copy_on_write_friendly = true
end

before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = APP_PATH + "/Gemfile"
end

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{ server.config[:pid] }.oldbin"
  unless old_pid == server.pid
    begin
      Process.kill :QUIT, File.read(old_pid).to_i
    rescue Errno::ENOENT, Errno::ESRCH

    end
  end
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

最後にここまでの内容をGitHubに反映しておきましょう。

$ git add .
$ git commit -m "first_commit"
$ git push origin master

デプロイ!

これでようやくデプロイに必要な設定が終了しました!
いやー長かった…

というわけで早速デプロイができる状態なのかをチェックしていきます。

(sample_app)

 $ bundle exec cap production deploy:check

すると順々に処理が走っていき、以下のようなエラーが発生すると思います。

00:10 deploy:check:linked_dirs
      01 mkdir -p /var/www/sample_app/shared/log /var/www/sample…
    ✔ 01 sample_user@3.21.59.95 0.675s
00:10 deploy:check:make_linked_dirs
      01 mkdir -p /var/www/sample_app/shared/config
    ✔ 01 sample_user@3.21.59.95 0.554s
00:12 deploy:check:linked_files
      ERROR linked file /var/www/sample_app/shared/config/databa…

これは/sample_app/shared/config配下にdatabase.ymlが存在しませんというエラーです。

実はCapistranoのdeployコマンドを実行するとサーバー側のディレクトリの構造が少しだけ変化し、新たにsharedというディレクトリが生成されます。

/var/www/sample_app
[sample_user@ip-10-0-0-79 sample_app] $ ls 
releases  shared

そのためshared配下にdatabase.ymlを作成、編集していきます。

/var/www/sample_app/shared/config
[sample_user@ip-10-0-0-79 config] $ vim database.yml

-----------------------------------

default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3



production:
  adapter: mysql2
  pool: 5
  database: sample_app_db #RDSに設定したデータベース名
  host: database-1.ckbaeqyxwuvr.us-east-2.rds.amazonaws.com #エンドポイント
  username: sample_user #RDSに設定したuser名
  password: password #RDSに設定したパスワード
-----------------------------------

スクリーンショット (43).png

localにあるdatabase.ymlにproduction環境のみ変更を加えました。
新たにRDSの情報を記載することで、RDSをデータベースとして使用することが可能です。さらにこちらの内容をlocalにもコピーしておきましょう。

この状態でdeploy:checkを実行すると、同様にsecrets.ymlがないといったエラーも発生してしますので、事前に作成します。

/var/www/sample_app/shared/config
[sample_user@ip-10-0-0-79 config] $ vim secrets.yml

-------------------------------------------------
development:
  secret_key_base: bf8daa05189f332e986f7fcb26bbb25c9c34da0257b9994931dd0f5265e325f3a84c9630b1e264b96c8e28276ab7bc41a9c6761b8b2befeb1bd53bbcb53afb59

test:
  secret_key_base: 0c1f0d49d25f201c31378d38eb12cf87f4684f321ed0f2b1b66f704c6daf77690f487c77ab6347d1ddf5bfc3c258048be5ca34e406c0d4de34599305623f699d

# Do not keep production secrets in the unencrypted secrets file.
# Instead, either read values from the environment.
# Or, use `bin/rails secrets:setup` to configure encrypted secrets
# and move the `production:` environment over there.

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
-------------------------------------------------

これでlocalに戻り、もう一度deploy:checkを実行すると、今度はエラーがなく処理が終わるはずです。以下のコマンドで本デプロイを行って下さい。

sample_app
 $ bundle exec cap production deploy

以下のようにエラーが出なればデプロイ完了です。

01:27 deploy:cleanup
      Keeping 3 of 33 deployed releases on 3.21.59.95
      01 rm -rf /var/www/sample_app/releases/20200227082245 /var/www/sample_app/releases/20200227082547 /var/www/ …
    ✔ 01 sample_user@3.21.59.95 0.899s
01:31 deploy:log_revision
      01 echo "Branch master (at 803b41a3fe36f77c2682d9f740f4dbd45047b08d) deployed as release 20200228055144 by  …
    ✔ 01 sample_user@3.21.59.95 0.826s

そして最後の仕上げにsecret_key_baseを生成してsecrets.ymlに張り付けましょう。

デプロイ自体にエラーは出ていませんが実はこの状態でアクセスしてもページが表示されません。

そのためunicornのエラーログを確認してみると…

current/unicorn_error.log
[sample_user@ip-10-0-0-79 ~] $ cat /var/www/sample_app/current/log/unicorn_error.log

I, [2020-02-28T05:52:58.354411 #23838]  INFO -- : worker=2 ready
I, [2020-02-28T05:52:58.420071 #23777]  INFO -- : reaped #<Process::Status: pid 23780 exit 0> worker=0
I, [2020-02-28T05:52:58.420171 #23777]  INFO -- : reaped #<Process::Status: pid 23781 exit 0> worker=1
I, [2020-02-28T05:52:58.420211 #23777]  INFO -- : reaped #<Process::Status: pid 23782 exit 0> worker=2
I, [2020-02-28T05:52:58.420260 #23777]  INFO -- : master complete
E, [2020-02-28T06:05:54.876223 #23838] ERROR -- : app error: Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml` (RuntimeError)

とsecret_key_baseがないとのエラーが発生しているのが分かります。
(currentディレクトリはCapistranoのデプロイによってデプロイ先の配下に新しく生成されるディレクトリで、ここにGitt Hubからコードがcloneされます。)
なので

[sample_user@ip-10-0-0-79 ~] $ cd /var/www/sample_app
[sample_user@ip-10-0-0-79 current] $ bundle exec rake secret

81734ede2dfc8644523baabe7b8614081c53c43580feb5f9f23140d946040d22dfe2324756eedd7d103057718fc28587e7b57619f7eb077f57054a

[sample_user@ip-10-0-0-79 current] $ vim secrets.yml

----------------------------------------------

# Do not keep production secrets in the unencrypted secrets file.
# Instead, either read values from the environment.
# Or, use `bin/rails secrets:setup` to configure encrypted secrets
# and move the `production:` environment over there.

production:
  secret_key_base: 81734ede2dfc8644523baabe7b8614081c53c43580feb5f9f23140d946040d22dfe2324756eedd7d103057718fc28587e7b57619f7eb077f57054a

----------------------------------------------
[sample_user@ip-10-0-0-79 ~] $ exit

#local
$ bundle exec cap production deploy
# 再度デプロイ

一度デプロイが成功すると後は変更があった時に
git push → cap production deploy を実行するだけでデプロイ先に内容が反映されるのでデプロイ作業が大幅に楽になります。

それではサーバーにアクセスしてみて、作ったAPPが存在するかを確認してみてください。

スクリーンショット (1).png

あったぁ!

スクリーンショット (50).png

日本語登録も大丈夫です。

まとめ

初めてAWSを利用したサーバー構築と自動デプロイを行ったのですが結構つまづくポイントが多く時間を費やしてしまったため、これを機にAWSやサーバー、データベースといったWebの基礎をもう一度学び直そうと思います。

長くなってしましましたがお読みいただきありがとうございました。

参考記事

こちらの記事を参考にデプロイと記事を書かせていただきました。ありがとうございました。

Rails4+Capistrano3+Nginx+Unicorn EC2へのデプロイ

世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで

7
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
14