AWSへのRailsアプリのデプロイ その2


はじめに

今回は以下の記事の続きです。アプリのデプロイまで行っていきます。
AWSへのRailsアプリのデプロイ その1

データベースのインストール

以下のコマンドでバージョン5.6をインストールします。
バージョンについては、各々の環境ごとに適当なものを選択してください。

sudo yum -y install mysql56-server mysql56-devel mysql56

さっそくmysqlを立ち上げます。

sudo service mysqld start

mysqlのrootユーザーのパスワードを設定します。

sudo /usr/libexec/mysql56/mysqladmin -u root password 'ここにパスワードを入力'

パスワードが設定できたか確認します。

mysql -u root -p

パスワードの入力を促されるため、先ほど設定したパスワードを入力します。

Enter password: 

mysqlへのログインが正常終了すれば「mysql>」が表示されSQL文を実行できるようになります。

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.47 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

これでmysqlのインストールは完了です。quitでログアウトしておきましょう。

mysql> quit

EC2インスタンスからGitHubにSSH接続する

デプロイを行う際にGitHubからEC2へコードをクローンする必要があります。
以下のコマンドで公開鍵と秘密鍵のペアを作成しましょう。

ssh-keygen -t rsa -b 4096

これで.sshディレクトリの配下に鍵ができるので、catで公開鍵の内容を確認しGitHubに登録します。

cat /home/ec2-user/.ssh/id_rsa.pub

以下のURLからGitHubに公開鍵を登録しましょう。
https://github.com/settings/keys


これでGithubにアクセスできるはずなので、EC2上からsshコマンドを実行してみましょう。
「Hi!"ユーザー名"」 と表示されればOKです。

アプリケーションサーバ(unicorn)の設定。

unicornの設定を行うため、まずはローカルでの作業を行います。Gemfileに以下を追記しましょう。
production do の中に記載することで、本番環境でのみunicornを使うことになります。

group :production do
  gem 'unicorn', 'インストールしたいバージョン'
end

gemのインストールも忘れずに。

bundle install

ちょっと長いですが、config/unicorn.rbを以下のように編集します。

app_path = File.expand_path('../../', __FILE__)

worker_processes 1

working_directory app_path

pid "#{app_path}/tmp/pids/unicorn.pid"

listen 3000

stderr_path "#{app_path}/log/unicorn.stderr.log"

stdout_path "#{app_path}/log/unicorn.stdout.log"

timeout 60

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

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

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end

あとはmasterブランチにpushして完了です。

GitHubからコードをクローンする

EC2インスタンスにディレクトリを作り、権限をec2-userに変更します。

sudo mkdir /var/www/
sudo chown ec2-user /var/www/

コードをクローンするためにはリポジトリのURLが必要なので、以下の赤枠内のボタンからURLを取得します。

取得したURLでコードをクローンしましょう。

cd /var/www/
git clone https://github.com/naoto-ysd/freemarket.git

この時点で/var/wwwの配下にアプリがクローンされていると思います。
アプリのディレクトリ内に移動し、各種設定を行いましょう。

$ pwd
/var/www
$ ls -l
合計 4
drwxrwxr-x 15 ec2-user ec2-user 4096  5月 31 14:43 アプリ名

Swap領域を用意する

Swap領域を用意し、メモリ不足に備えておきましょう。
ホームディレクトリで以下のコマンドを入力。

sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
sudo chmod 600 /swapfile1
sudo mkswap /swapfile1
sudo swapon /swapfile1

gemのインストール

一旦アプリをクローンしたディレクトリに移動します。

cd  /var/www/アプリ名

本番環境でgemを管理するためにbundlerをインストールします。
ローカルで以下のコマンドを実行してbundlerのバージョンを確認しましょう。

bundler -v

これで、ローカル側で使っているバージョンが分かりましたので、EC2上でbundlerのバージョンを指定してインストールします。

gem install bundler -v バージョン

bundle installも忘れず実行。

bundle install

環境変数の設定

パスワードなどのセキュリティに関わる情報は環境変数に設定します。
まずsecret_key_baseを作成しましょう。
EC2上で以下を実行します。

cd /var/www/アプリのディレクトリ

rake secretでcookieの暗号化に文字列を作成します。
このコマンドで生成する文字列は、後から環境変数に設定するのでコピーしておきましょう。

rake secret

/etc/environmentを編集して環境変数を設定しましょう。

sudo vim /etc/environment
DATABASE_PASSWORD='MySQLのrootユーザーのパスワード'
SECRET_KEY_BASE='先程コピーしたsecret_key_base'

環境変数を反映させるため、一度ここでログアウトしてから再度EC2にログインてください。
再度ログインしたら、環境変数が設定されているはずなので、envコマンドで確認します。

env | grep DATABASE_PASSWORD
env | grep SECRET_KEY_BASE

ポートの解放

現時点ではEC2インスタンスがhttpで通信できない状態です。
インバウンドルールを編集し、ポートを解放してあげましょう。

先程作成したrunicorn.rbでlisten 3000と記述したので、今回デプロイするアプリではポート番号3000を使うことになります。
インバウンドルールにポート番号3000を追加して、作業は完了です。

Railsを起動させる。

Railsを起動させる前にDBの設定を行います。
ローカル環境でdatabase.ymlを編集してproduction: 以下を変更しましょう

production:
  <<: *default
  database: "アプリ名によって異なる。変更不要"
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

ローカルでの変更をコミットしてGithubにプッシュした後、EC2インスタンス上にコードを反映させます。

git pull origin master

EC2インスタンス上にデータベースを作成してマイグレーションしましょう。

rails db:create RAILS_ENV=production
rails db:migrate RAILS_ENV=production

このままの状態だとアセットファイル(画像やjsのこと)がコンパイルされていないので、ビューが崩れてしまいます。
事前にコンパイルを行っておきましょう。

rails assets:precompile RAILS_ENV=production

それではEC2インスタンスでRailsを起動させます。
アプリのディレクトリに移動してから、ユニコーンを起動させるコマンドでRailsを起動させることができます。
-cオプションで設定ファイルのパスを指定し、-E で本番環境で作動させています。

cd /var/www/アプリ名/
bundle exec unicorn_rails -c config/unicorn.rb -E production -D

ここまで出来ればデプロイできたはずなので、実際にブラウザでアプリにアクセスしてみましょう。
http://"Elastic IP":3000
エラーが起きた場合、以下のファイルにエラーログが出力されているので、こちらを確認してみてください。

tail -f /var/www/freemarket/log/unicorn.stderr.log

ウェブサーバのインストール

ウェブサーバとしてNginxをEC2にインストールします。

sudo yum -y install nginx

インストールが終了したら、/etc/nginx/conf.d/rails.confを以下のように編集しましょう。
アプリケーション名やElasticIPは適宜読み替えてください。

upstream app_server {
  server unix:/var/www/アプリケーション名/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name Elastic IP;

  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;
}

nginxの権限も変更しておきます。

sudo chmod -R 775 /var/lib/nginx

nginxを再起動させて設定ファイルを読み込ませましょう。

sudo service nginx restart

unicorn関係の修正

現在はunicorn.rbのlistenという項目に3000が指定されていると思います。
それを以下のように修正し、Githubへプッシュしましょう。

listen "#{app_path}/tmp/sockets/unicorn.sock"

EC2への反映も忘れずに。

git pull origin master

unicornを再起動させるため、unicornのプロセスIDを確認します。

ps aux | grep unicorn

ec2-user 14750  0.0 11.6 504768 117792 ?       Sl   Jun01   0:02 unicorn_rails master -c config/unicorn.rb -E production -D                                                                                            

プロセスID14750をkillしましょう。

kiill 14750

これでRailsを再起動させればアプリケーションにアクセスできるはずです。
http://"Elastic IP" (URLにポート番号の指定は不要です。)

RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D

Railsの起動でエラーが出たら

以下の方法でエラーの解決方法を調査してみましょう。

・ログの確認
/var/www/アプリ名/log/unicorn.stderr.log
/var/log/nginx/error.log

・以下を再起動してみる
MySQL
Nginx
EC2

いったん完結

アプリのデプロイまで出来たため、前回の記事と合わせていったん完結です。
私の気力次第で自動デプロイについての記事も書きます。