Edited at

インフラエンジニアじゃなくたってこのぐらいは知っておきたいRailsサーバ構築手順

More than 1 year has passed since last update.

株式会社LITALICOでエンジニアをやっております@Takuan_Oishiiです。

この記事は『LITALICO Advent Calendar 2016』4日目の記事です.

4日目は初心者WebエンジニアまたはRailsは書けるけどサーバ構築とかシラネという読者を対象にしたサーバ構築手順をお届けします🎁


はじめに

LITALICOでは新卒エンジニアの入社時の研修の題材のひとつとしてRuby on Rails Tutorialを利用しています. RubyとRailsの学習のみならず, テストなどのWebアプリ周辺知識を習得できるので重宝しています.

ただし, 実際に仕事をしていく上では「Webサーバってどうやって設定して起動すんの?」「デプロイってどうやんの?」という知識が0の状態だと結構キビしいと思います. そしてその知識はRails Tutorialのカバー範囲外です.

個人的な考えでは, こういうのは見よう見まねでもいいので自分で一回やっておけば「次に何をググったらいいのか」がわかるようになって, 勉強の取っ掛かりになると思っています.

ということで誰でもWebアプリを公開できる手順書を作りました.

ただし扱う内容が多岐に渡りますし, 前述の通り手順書の通り手を動かすことによって勉強の取っ掛かりにするのを目的としているので, それぞれの項目の細かい解説まではしません.

また, デプロイするRailsアプリとしてRails Tutorialの2.3.4までで完成するToyアプリケーションを使用することにします.


今回扱うもの


  • EC2

  • Amazon Linux(CentOSに置き換えて考えることもたぶん可)

  • Apache 2.4

  • Phusion Passenger 5.0

  • MySQL 5.7

  • Ruby 2.3

  • Ruby on Rails 5.0

  • Capistrano 3.6

また, ローカルの環境としてOS Xを使用しています.

ローカルがLinux環境の場合は問題になることはあまりないと思いますが, Windows環境の人はSSHの設定等をよしなに読み替えて下さい.


手順


IAMでAWSコンソールへのログイン

AWSアカウントの作成は以下を見ればわかると思います.

AWS アカウント作成の流れとポイント | AWS

IAMユーザの作成とAWSコンソールへのログインは以下を見ればいいと思います.

IAM ユーザーを作成する - Amazon EC2 でのセットアップ - Amazon Elastic Compute Cloud

ログインしたら東京リージョンを選択しておきます.(実際のところリージョンはどこだっていいんですが)

矢印部分をクリックすると選べます. 既に東京になってる場合はそのままでいいです.

以後のAWSコンソール上で行うすべての手順は, 東京リージョンが選択されている状態で行うようにしてください.


EC2インスタンスを立てる


下準備

まずはEC2ダッシュボードを開きます.

次にSSHログインで必要になるのでキーペアを作ります.

画面左のメニューの「ネットワーク&セキュリティ」内の「キーペア」をクリックするとキーペア管理画面になります.

「キーペアを作成」ボタンをクリックしてキーペア名を入力すると作成が完了し, 秘密鍵がダウンロードされます. 名前は適当に「web-server-key」とでもしておきます.

秘密鍵はこの作成時のタイミングでしかダウンロードできないので大事に保管しておきましょう.

次にセキュリティグループを作成します.

キーペア同様に「ネットワーク&セキュリティ」内の「セキュリティグループ」をクリックするとセキュリティグループ管理画面になります.

既にデフォルトのセキュリティグループが1つ存在しているはずなので, そのセキュリティグループを右クリックして「インバウンドルールの編集」を選択します.

「タイプ」が「全てのトラフィック」となっている行が1行だけあるはずなので, その行の「タイプ」を「SSH」に変更し, 「送信元」は「マイIP」にします.

「ルールの追加」をクリックして2行目を作成し, 2行目はタイプ:HTTPで, 送信元:任意の場所 にしておきます.

「保存」を押したら完了です.


インスタンス作成と起動

画面左のメニューの「インスタンス」内の「インスタンス」をクリックするとインスタンス管理画面になります.

「インスタンスを作成」をクリックすると作成手順が開始されます. 以下の画像のような感じで進んでいきます.

どの手順でどんな選択をしていくかだけを以下に書きます. 言及されていない項目についてはデフォルトのままで構いません.

1つの手順が終わったら画面右下にある「次の手順」ボタンを押します.


  • AMIの選択


    • 「Amazon Linux AMI」を選択



  • インスタンスタイプの選択


    • t2.smallを選択



  • インスタンスの詳細の設定


    • 「自動割り当てパブリック IP」を「有効化」



  • ストレージの追加


    • 全てデフォルトでOK



  • Add Tags


    • 「値」欄に「web-server」



  • セキュリティグループの設定


    • 「セキュリティグループの割り当て」を「既存のセキュリティグループを選択する」

    • 先程編集したデフォルトのセキュリティグループが表示されるのでチェックを入れる


      • インバウンドルールとしてHTTPとSSHが表示されていることを確認しましょう.





  • 確認


    • 「作成」ボタンを押し, キーペアを選択する.


      • 「既存のキーペアの選択」と, 「web-server-key」を選択し, 注意文にチェックを入れる.





最後に「インスタンスの作成」ボタンをクリックするとインスタンスが作成され, 起動します.

インスタンス管理画面からもインスタンスが追加されていることがわかります.

インスタンスをクリックすると下部に情報が表示されるので, その中からパブリックIPを確認しておきましょう.


sshログイン

~/.ssh/config を書いておくと楽なので以下のように設定します.

# ~/.ssh/config

Host web-server
HostName #インスタンス管理画面で確認したパブリックIP
User ec2-user
IdentityFile /path/to/web-server-key.pem

秘密鍵はパーミッションが600でないとsshさせてくれませんので変えておきます.

$ chmod 600 /path/to/web-server-key.pem

ではログインです.

$ ssh web-server

こんなログインメッセージが出てきたらOK.

       __|  __|_  )

_| ( / Amazon Linux AMI
___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.09-release-notes/
6 package(s) needed for security, out of 11 available
Run "sudo yum update" to apply all updates.

おまけですが起動後はこんなのをやっておくといいかもしれません. 今回は解説をかんたんにするためやらずに進めます.

AWS EC2 Amazon Linuxインスタンス起動後、最初にやることまとめ


Apacheインストール

インスタンスにapache2.4をインストールして動作確認してみます.

$ sudo yum install -y httpd24

$ sudo service httpd start

これでもうインスタンスはwebサーバとして動作しはじめています.

ブラウザにパブリックIPを入力すれば以下のような画面が出るはずです.


MySQLインストール

MySQL5.7をインストールしてみて動作確認してみます.

# このURIは記事執筆時点での最新リポジトリです. 

$ sudo yum -y install http://dev.mysql.com/get/mysql57-community-release-el6-9.noarch.rpm
$ sudo yum install -y mysql-community-server mysql-devel
$ sudo service mysqld start

mysql5.7ではデフォルトのrootパスワードが設定されていて, そのパスワードはmysqldのログファイルに出力されています.

$ sudo grep 'temporary password' /var/log/mysqld.log 

でデフォルトパスワードを確認してログインしてみます.

$ mysql -u root -p

ログインはできても, パスワードを変更しない限りは何もさせてくれないのでパスワードを変更します.

パスワードは最低1つの数値文字を含み1つの小文字および大文字を含み1つの特殊文字を含む必要があります.

以下のは例です. 実際はいい感じのパスワードにして下さい.

また, 本来なら作業用のユーザーを作成すべきですが解説が面倒なので以降rootで作業を進めることにします.

mysql> set password for root@localhost=password('passPASS@999');

Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> quit


Rubyインストール


必要なパッケージとrbenvインストール

$ cd

$ sudo yum install -y git gcc openssl-devel readline-devel zlib-devel

$ git clone https://github.com/rbenv/rbenv.git .rbenv
$ git clone https://github.com/rbenv/ruby-build.git .rbenv/plugins/ruby-build

$ echo 'export RBENV_ROOT="${HOME}/.rbenv"' >> .bash_profile
$ echo 'export PATH="${RBENV_ROOT}/bin:${PATH}"' >> .bash_profile
$ echo 'eval "$(rbenv init -)"' >> .bash_profile
$ source .bash_profile


いざインストール

# 最新のRubyを確認

$ rbenv install --list

# 最新のRubyをインストール (記事執筆時点では2.3.3が最新)
$ rbenv install 2.3.3
$ rbenv rehash
$ rbenv global 2.3.3

# 2.3.3ならOK!
$ ruby -v


デプロイの準備


bundlerとpassengerのインストール

$ sudo yum install -y gcc-c++ libcurl-devel httpd24-devel

$ gem install bundler
$ gem install passenger

# このコマンドは対話的に処理が進んでいくが基本的には何か言われたらエンターを押してればOK
# 最後だけちょっと作業がある
$ passenger-install-apache2-module

passenger-install-apache2-moduleコマンドの最後で

Please edit your Apache configuration file, and add these lines:

LoadModule passenger_module /home/ec2-user/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/passenger-5.0.30/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /home/ec2-user/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/passenger-5.0.30
PassengerDefaultRuby /home/ec2-user/.rbenv/versions/2.3.3/bin/ruby
</IfModule>

などと言われるので, これが出たら別なターミナルウィンドウでsshして以下のように作業します.

$ sudo vi /etc/httpd/conf.d/passenger.conf

# このファイルを以下のようにpassengerに指示された内容にする.
LoadModule passenger_module /home/ec2-user/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/passenger-5.0.30/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /home/ec2-user/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/passenger-5.0.30
PassengerDefaultRuby /home/ec2-user/.rbenv/versions/2.3.3/bin/ruby
</IfModule>

作業が終わったらもとのpassenger-install-apache2-moduleコマンドの方のウィンドウに戻り, エンターを押す.

作業が正しくできていればEverything looks good. :-)と言ってくれます.

ここからの作業はローカルでの作業になるのでインスタンスからは一旦ログアウトしておいても構いません.


デプロイするアプリとそのリポジトリの準備

冒頭で述べた通り今回デプロイするアプリはRails Tutorialの2.3.4までで完成するToyアプリケーションです.

ここでは, 2.3.4の状態まで進めてあるリポジトリを利用する前提で解説します. もちろん自分で準備しても構いません.

このリポジトリがチュートリアルの2.3.4の状態と違うのは, GemfileとCapistranoの設定ファイルだけです.

Gemfileは, MySQLを使用するためにpgsqlite3が消えていて, 代わりにmysql2が増えています.

Capistranoの設定ファイルはCapfileconfig/deploy.rbconfig/production.rbの3つです.

このリポジトリをcloneしてcapistranoでデプロイできるようにします.

$ git clone https://github.com/takuan-oishii/toy_app.git

$ cd toy_app
$ bundle install
$ bundle exec cap -T

これでローカルでの準備は完了です.


インスタンス側のデプロイ準備

いよいよwebアプリを動かす準備です. インスタンスにSSHログインして以下のコマンドを実行していきます.

$ sudo vi /etc/httpd/conf.d/toy_app.conf

# toy_app.confに以下を書き込む
<VirtualHost *:80>
ServerName top_app
DocumentRoot /home/ec2-user/toy_app/current/public
RailsEnv production
<Directory /home/ec2-user/toy_app/current/public>
Require all granted
AllowOverride all
Options -MultiViews
</Directory>
</VirtualHost>

$ sudo vi /etc/httpd/conf.d/welcome.conf
# welcome.confの内容を全て#でコメントアウトする

$ sudo service httpd restart

$ sudo yum install -y nodejs --enablerepo=epel

$ echo 'export DB_PASSWD=mysqlのrootのパスワード' >> .bashrc
$ mysql -u root -p
mysql> create database toy_app_production;
mysql> quit


デプロイ実行

ローカルで

$ bundle exec cap production deploy

を実行してデプロイを試してみます.

apacheのインストールを確認したときと同様にブラウザで見てみると403エラーの画面になると思います.

これはrailsアプリが置いてあるディレクトリのパーミッションの問題なので, インスタンスにSSHログインして

$ sudo chmod -R 755 /home/ec2-user

をしてみるとでなくなると思います.

が, 今度は「Incomplete response received from application」などと言われて502エラーになると思います.

これはsecret_key_baseを準備していないために出てるものなので, インスタンスにSSHログインして

$ cd toy_app/current

$ bundle exec rails secret
# 出てきた文字列はコピーしておく
$ echo 'export SECRET_KEY_BASE=コピーしたやつ貼り付け' >> ~/.bashrc
$ passenger-config restart-app

これでようやくrailsチュートリアルのアプリケーションが動くようになりました!!


おわりに

herokuなんかを使ってしまえば一瞬でデプロイ&公開できてしまいますが, 自分でやろうとするとこれくらい長々と作業が必要になります.

楽できるに越したことはないですが, 自分で一度やってみることによって色々と勉強になる部分もとても多いと思います.

ちなみに今回は色々と省略しているので実際に本番用のサーバとして稼働させるには不備も多くあります. (たとえばnew userのフォームに日本語を入力すると500エラーになってしまいます)

そのへんも勉強してみると面白いと思います.

幸いにしてAWSのようなクラウドサービスを使えば, 失敗してもインスタンスごと落とせばかんたんにやり直すことが出来ます. 初心者プログラマでもビビらずに色々と自分でいじって勉強してみましょう👍

明日の『LITALICO Advent Calendar 2016』は@negiさんのHTMLメールを作成する上での注意点についての記事です. お楽しみに.