Help us understand the problem. What is going on with this article?

(デプロイ編②)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで

More than 1 year has passed since last update.

世界一丁寧なAWS解説シリーズ 項目表

No. タイトル
1 下準備編
2 DB・サーバー構築編
3 デプロイ編①
4 〜〜デプロイ編②(今ここ)〜〜
5 Capistrano編

「分かりづらいAWSやネットワークを、出来るだけ丁寧に」
と思って記事を書き続けたら、まさかの4部作になってしまいました... 笑

いよいよほんとにラストです。
最後まで頑張りましょう!(と、言い聞かせている相手は自分ですw)

前回までの記事で、
AWS側の準備→作成したアプリをgitからクローン というところまで行いました。
(まだの方は、 1.下準備編 2.DB、サーバー編 3.デプロイ編① をお読みください。)

このクローンしたアプリを、実際に動かすにはまだ準備が必要です。
まずは、Unicornのインストール...の前に、webサーバー/アプリケーションサーバー/Rackの違いから見ていくこととしましょう。

Webサーバー/アプリケーションサーバー/Rackとは?

さて突然ですがここで皆さんに問題です。
開発環境において、rails s のコマンドを打ち込んで起動するサーバー(WEBrick)は、Webサーバーですか? アプリケーションサーバーですか?
正解は...........アプリケーションサーバーです。

それぞれの違いを見ていきましょう。

Webサーバーとは、ユーザーから送られてきた自サイトへのリクエストを受け取り、なんらかの処理を加えるプログラムです。
本番環境にあがっているプロダクトの場合、ユーザーからのリクエストは大半がまずここに送られます。 「受付窓口」といったイメージですね。

middleware1.png

この受付が「自分だけで処理できる!」と判断すれば、ちょいちょいっと作業をした上で、ユーザーにレスポンスを返します。
逆に「自分だけじゃ無理!」と判断した場合は、処理をアプリケーション本体に投げます。そして、アプリケーション側から返ってきたレスポンスをユーザーに返すのです。

では、その「アプリケーション本体」はどこに置かれているのか。
その答えが、アプリケーションサーバーになります。

middleware2.png

アプリケーションサーバーには、ご自身で作られたアプリケーションが置かれています。
Webサーバーから「僕だけじゃ無理です。助けてください」との依頼を受けたアプリケーションサーバーは、自身の中にいるアプリ本体に指令を出し、処理完了後、webサーバーに対して「終わりましたよー」と報告をするのです。

ですが、ここで一つ問題があります。
アプリケーションサーバーとアプリ本体は、使用している言葉が違うので、上手くコミュニケーションが取れないのです。

さて困った。と思った矢先、登場するのがRackです。
Rackは、いわば通訳です。
彼が通訳をしてくれるお陰で、無事にアプリケーションサーバーとアプリ本体がコミュニケーションを取ることができ、結果、ユーザーにレスポンスを返すことができたのでした。
ちゃんちゃん。

middleware4.png

... と、なんとなくイメージは掴めましたか? 笑

ちなみに冒頭の問題に関してなのですが、
大半のアプリケーションサーバーは、webサーバーを使わずに単体で実行できます。
(本番環境ではwebサーバーを設置することがほとんどですが)
ですので、正解は、アプリ本体を設置する「アプリケーションサーバー」...となるのです。

この違いを頭に入れた上で、それぞれをインストールしていきましょう。

Unicornの設定

Unicornとはアプリケーションサーバーの一種です。
先ほど出てきましたね。アプリ本体を格納するためのサーバーです。

分かってしまえばこっちのもの。
早速インストールしていきましょう。
下記コマンドを実行して下さい。

[naoki|mumu] $: vi Gemfile
-----------------------------
#以下を追記
group :production, :staging do
    gem 'unicorn'
end
----------------------------
[naoki|mumu] $ gem install bundler
[naoki|mumu] $ bundle install
[naoki|mumu] $ vi config/unicorn.conf.rb
----------------------------

打ち込むコマンド自体は見慣れたものばかりですね。
viコマンドでconfig配下に生成したunicornの設定ファイルに、下記を記述します。

unicorn.conf.rb
  # set lets
  $worker  = 2
  $timeout = 30
  $app_dir = "/var/www/rails/mumu" #自分のアプリケーション名
  $listen  = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
  $pid     = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
  $std_log = File.expand_path 'log/unicorn.log', $app_dir
  # set config
  worker_processes  $worker
  working_directory $app_dir
  stderr_path $std_log
  stdout_path $std_log
  timeout $timeout
  listen  $listen
  pid $pid
  # loading booster
  preload_app true
  # before starting processes
  before_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        Process.kill "QUIT", File.read(old_pid).to_i
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
  end
  # after finishing processes
  after_fork do |server, worker|
    defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
  end

ここら辺は設定ファイルなので、詳細には追いません。
これでUnicornの設定が完了です。

Nginxの設定

お次はNginxです。「エンジンエックス」と読むそうです。
このNginxはWebサーバーにあたります。
これも先ほど出てきましたね。受付窓口です。

早速下記コマンドを打ち込んでください。

[naoki|~] sudo yum install nginx
[naoki|~]$ cd /etc/nginx/conf.d/
[naoki|conf.d]$ sudo vi mumu.conf #自分のアプリケーション名でファイル名変更

viコマンドで作成したnginxの設定ファイルには、下記を記述します。

mumu.conf
# log directory
error_log  /var/www/rails/mumu/log/nginx.error.log; #自分のアプリケーション名に変更
access_log /var/www/rails/mumu/log/nginx.access.log; #自分のアプリケーション名に変更
# max body size
client_max_body_size 2G;
upstream app_server {
  # for UNIX domain socket setups
  server unix:/var/www/rails/mumu/tmp/sockets/.unicorn.sock fail_timeout=0; #自分のアプリケーション名に変更
}
server {
  listen 80;
  server_name ~~~.~~~.~~~.~~~;(#アプリのElastic IPに変更してください)
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;
  # path for static files
  root /var/www/rails/mumu/public; #自分のアプリケーション名に変更
  # page cache loading
  try_files $uri/index.html $uri.html $uri @app;
  location @app {
    # HTTP headers
    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;
  }
  # Rails error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/www/rails/mumu/public; #自分のアプリケーション名に変更
  }
}

ここも設定ファイルなので詳細には追いません。
また、設定ファイルの記述が終わったら、下記も実行してください。

[naoki|conf.d] cd /var/lib
[naoki|lib] sudo chmod -R 775 nginx

この呪文はpostメソッドでもエラーが出ないようにするためのものなのだとか。
「開けごま」的な勢いでとりあえず唱えてあげましょう。

これにて設定完了です。

MySQLの設定

続いてDBです。
(アプリケーションのDBがMySQLで作成されている前提で話を進めていきます。)

下記コマンドを打ち込み、MySQLに関する設定を変更していきましょう。

[naoki|protospace]$ vi config/database.yml
----------------------------
  production:
    <<: *default
    database: mumu_production
    username: root #ここをrootに変更する
  password:      #ここを空欄にする
----------------------------

[naoki|mumu]$ sudo service mysqld start #mysqldの起動
[naoki|mumu]$ ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock
[naoki|mumu]$ rake db:create RAILS_ENV=production
[naoki|mumu]$ rake db:migrate RAILS_ENV=production

my.cofとはMySQLのオプション設定向けファイルです。
ここに文字コードを設定した上で、mysqidを起動させます。
mysqlとmysqld... この「d」は一体なんなのでしょうか。
実はこの「d」は「デーモン」のdを指しており、デーモンとはバックグラウンド処理のことを指します。
つまり、mysqldとは、mysqlの裏側の処理を担当する箇所で、
クライアントからmysqlに送られた来たSQL等を処理し、結果をクライアントに返すという役割を担っている箇所となります。

このmysqldを起動させ、MySQLが動く状態にした上で、
In -sコマンドで、ローカル環境で起動させているMysqlの場所を本番環境に合わせれるようリンクを作成し、
そしていつもの、「rake db:create」「rake db:migrate」を実行です。

migration.png

上記のように、
アプリのmigrationファイルが実行されたログが出て来れば無事成功です。

(権限が原因でmysqldの起動が出来ないことがあります。その場合はchownやchmodコマンドでmysql関連ファイルの権限を変更してあげましょう。)

Nginxの起動

先ほど設定したNginxを起動させましょう。
使うはたった1行のコマンド。

[naoki|mumu]$ sudo service nginx start

これだけです。
そして全ての行程が上手くいっていれば、これが打ち込む最後のコマンドになります。
なんて感慨深いのでしょう。
涙が出そうです。(ほんとに)

確認!!!!!!

さぁ、これで全行程が終了しました。
52.64.~~~~~~~~~(ご自身のIPアドレス)
にアクセスし、作成したアプリがきちんとデプロイされたか確認してみてください。

ん...?
あ...
あれ...?
あれれ....???

something_went_wrong.png

MASAKANO
まさかの
エラーです。

あ... 慌てないでください...あわわわわ...
魔法のコマンド、再起動の出番です。

まずはUnicornの起動確認。

[mumu]$ ps -ef | grep unicorn | grep -v grep

このコマンドを打ち込んで、

naoki  24265     1 27 03:12 ?        00:00:01 unicorn_rails master -c /var/www/rails/tech-ruche/config/unicorn.conf.rb -D -E production
naoki  24271 24265  0 03:12 ?        00:00:00 unicorn_rails worker[0] -c /var/www/rails/tech-ruche/config/unicorn.conf.rb -D -E production
naoki  24273 24265  0 03:12 ?        00:00:00 unicorn_rails worker[1] -c /var/www/rails/tech-ruche/config/unicorn.conf.rb -D -E production
----------------------------

こんな感じでなんだかゴニョゴニョ表示されていれば既に起動されています。
表示されない場合は下記を実行してください。

[naoki]$ unicorn_rails -c /var/www/rails/mumu(アプリの名前)/config/unicorn.conf.rb -D -E production #unicornを起動させる

その後もう一度上記の起動確認コマンドを実行し、例のゴニョゴニョが出て来ればOKです。

その後、Nginxも再起動させます。

[naoki|mumu]$ sudo nginx -s reload

これでもう一度アクセスしてみてください!!
アプリが表示されましたか?
されてます...よね!?

ちなみに、画像の表示が出来ていない場合は、プリコンパイルが出来ていない可能性が高いです。
その際は、

1.unicornの停止(kill [PID])
2.rake assets:precompile RAILS_ENV=production の実行
3.unicornの再起動(上記コマンド)

を実施してみてください。
assets配下に画像を置いていると本番環境で反映されないこともあるみたいですので、画像は出来るだけpublic配下においてあげるようにしましょう。
(※特にbackgroundの画像表示に関してはこちらを参考にさせて頂きました。 ありがとうございます!)

以上で解説は終了です。
...が、きっとまだ表示されないという人もいるかと思います。
そんな方(と自分)の為に、いつの日かエラー対応集を作りたいなと思ってます。
なので、その日まではggrksで頑張ってください 笑
お疲れさまでした!!!

どうでしたでしょうか?
AWSにアプリをアップロードさせる過程を通じて、それなりにネットワーク関連の知識も付いたのではないでしょうか?

今回は解説しきれなかったですが、AWSにはまだまだ便利な機能が沢山あります(ERBやAuto Scalingなどなど...)
またデプロイの方法に関しても、CapistranoやBeansTalkなどを用いて更に簡単に行う手段も用意されています。

今回は勉強用に敢えて色々複雑にしてみましたが、今後のデプロイを考えるとCapistranoの方が良いので、Capistrano編も作ってみたいと思ってます。
お楽しみにー!

では、また会う日まで!

naoki_mochizuki
Keeyls株式会社のエンジニアしてます。 無人の鍵受け渡しシステムKEYSTATION(https://key-stations.com/ )や、 シェアオフィスの管理システム( https://sharedoffice-keystations.com/ )など作ってます。
https://keeyls.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away