RailsアプリをAWSにイチからデプロイするまでの手順メモ
2018年1月1日に「個人でWebサービス開発します!」と宣言して今日でまるっと一ヶ月経ちました。
それっぽいものは作れたので、公開に向けてあとひと押しというところです。
で、そのひと押しの中に「サーバーにデプロイする」という工程がありまして、最初はHerokuで全部やってしまおうと考えていたのですが、リージョンが米国なので通信速度が出なかったり、Dyno再起動すると画像が消えたりして非常に辛い思いをしたのでAWSで構築することにしました。
料金体制とか不安なところはありますが、今後必要なる知識だと思うので思い切ってトライ。
実装手順などをメモ代わりに残しておこうと思います。
STEP1 ネットワーク環境設定
まず最初にネットワーク周りやセキュリティ周りの設定を行います。
VPCの作成
- ネームタグに「VPCforアプリ名」
- IPv4 CIDR blockに「10.0.0.0/16」
- その他デフォルトで「作成」
サブネットの作成
- ネームタグに「アプリ名-Subnet-1a」
- VPCに先ほど作成した「VPCforアプリ名」
- アベイラビリティーゾーンに「ap-northeast-1a」
- IPv4 CIDR blockに「10.0.0.0/24」
- その他デフォルトで「作成」
RDS用にもう一つサブネットを作成。
アベイラビリティーゾーンを「ap-northeast-1c」に変える
※ネームタグ、IPv4 CIDR blockも変更されることを確認
インターネットゲートウェイの作成
- ネームタグに「Gatewayforアプリ名」
- 「作成」
- 作成した項目を選択し「VPCにアタッチ」
- VPCは「VPCforアプリ名」を選択して「アタッチ」
ルートテーブルの作成
- ネームタグに「Tableforアプリ名」
- VPCは「VPCforアプリ名」を選択して「作成」
- 下部のタブの「ルート」を選択
- 「編集」から「別ルートの追加」を選択
- 送信先に「0.0.0.0/0」
- ターゲットを「Gatewayforアプリ名」を選択
- 「保存」
サブネットとルートテーブルの関連付け
- 「アプリ名-Subnet-1a」を選択
- 下部のタブの「ルートテーブル」を選択
- 「編集」
- 「変更先」を「Tableforアプリ名」に変更
- 「保存」
- 「アプリ名-Subnet-1c」を選択
- 2-5と同様の操作を行う
セキュリティグループの作成
- ネームタグに「アプリ名-SecurityGroup」
- グループ名に「アプリ名-SecurityGroup」
- 説明に「Security for アプリ名」
- VPCは「VPCforアプリ名」
- 「作成」
- 下部のタブの「インバウンドルール」を選択
- 「編集」
- タイプは「SSH(22)」、送信元は「アプリ名-SecurityGroup」を選択
- 「別のルールの追加」
- タイプは「HTTP(80)」、送信元は「0.0.0.0/0」
- 「保存」
STEP2 RDSの設定
簡単に言うとデータベースです。
サブネットグループの作成
- 名前に「アプリ名_DB-Subnet-Group」
- 説明に「DB Subnet Group for アプリ名」
- VPC IDに「VPCforアプリ名」
- 「すべてのサブネットを追加」をクリック
- 自動的に追加されたことを確認し「作成」
DBインスタンスの作成
- 「DBインスタンスの起動」
- 好きなDBエンジンを選択 ※今回はMySQL
- DBエンジンのバージョンに「MySQL 5.7.19」、DBインスタンスクラスに「db.t2.micro」、マルチAZ配置を「いいえ」、ストレージタイプを「汎用(SSD)」に設定
- DBインスタンス識別子に「アプリ名-mysql」
- マスターユーザ、マスターパスワードを設定 ※よしなに
- 「次のステップ」
- VPCに「VPCforアプリ名」、サブネットグループに「アプリ名_DB-Subnet-Group」、パブリックアクセス「いいえ」、アベイラビリティーゾーン「指定なし」、VPCセキュリティグループに「アプリ名-SecurityGroup」
- データベースの名前に「アプリ名_production」、他はデフォルトでOK
- バックアップの保存期間を「1日」、他はデフォルトでOK
- 「DBインスタンスの作成」
ステータスが「利用可能」になるまでしばらく待ちましょう。
STEP3 EC2の設定
アプリケーションサーバーの中枢となる部分です。
インスタンスの作成
- リージョンが「アジアパシフィック(東京)」であることを確認
- 「インスタンスの作成」から「Amazon Linux」を選択
- インスタンスタイプは「t2.micro」を選択し「次の手順」
- ネットワークに「VPCforアプリ名」
- サブネットに「アプリ名-Subnet-1c」
- 念のため削除保護の有効化にチェック入れて「次の手順」
- ストレージの追加は行わずそのまま「次の手順」
- 「タグの追加」を選択し、キーに「Name」、値に「アプリ名」を入力し「次の手順」
- 「既存のセキュリティグループを選択する」にチェックを入れ「アプリ名-SecurityGroup」を選択
- 「確認と作成」
- 「起動」
- 「新しいキーペアの作成」を選択し、キーペア名に「アプリ名」
- 「キーペアのダウンロード」 ※あとで使う
- 「インスタンスの作成」からの「インスタンスの表示」
Elastic IPの割り当て
- 「新しいアドレスの割り当て」から「割り当て」を実行
- 成功したら「閉じる」
- 作成されたIPを選択し、「アクション」から「アドレスの関連付け」を選択
- インスタンスに作成したインスタンス名(手順通りだとアプリ名のはず)を選択
- 「関連付け」
インスタンスにSSHでログイン
- 「セキュリティグループ」から作成した項目を選択し、下部のタブの「インバウンド」を選択
- 「編集」からタイプ「SSH」のソースを「マイIP」に変更 ※現在のグローバルIP以外のSSHログインを制限できる
- 「保存」
- 「キーペアのダウンロード」で保存したpemファイルを
~/.ssh/
へ移動 権限を変更
1$ cd ~/.ssh/ && chmod 400 "アプリ名.pem"「インスタンス」から作成したインスタンス項目上で右クリックし「接続」を選択
「例:」と書かれた箇所にある
ssh -i "アプリ名.pem" ec2-user@割り当てたIPアドレス
をコピーしターミナルへ貼り付け、実行1$ ssh -i "アプリ名.pem" ec2-user@割り当てたIPアドレスなんかyesかnoか聞かれたら「yes」と入力
- EC2のアスキーアートが表示されたらSSHログイン完了
STEP4 サーバー環境を構築する
EC2にログインできたらいよいよNginxやRuby、MySQLなどをインストールしていきます。
Nginxの設定
サーバーをアップデート
1$ sudo yum updateNginxをインストール
1$ sudo yum install -y nginx起動
1$ sudo /etc/init.d/nginx start
管理ユーザーの作成
ユーザーを作成
1$ sudo adduser ユーザー名でマスター権限を付与
1$ sudo usermod -G wheel ユーザー名パスワードを設定
1$ sudo passwd ユーザー名設定を編集
1$ sudo visudoviが起動するので98行目あたりの
%wheel ALL=(ALL) ALL
のコメントアウト解除- 保存して終了(:x)
認証キーをユーザーディレクトリへ移動
1$ sudo rsync -a ~/.ssh/authorized_keys ~ユーザー名/.ssh/オーナーとグループを変更
1$ sudo chown -R ユーザー名r:ユーザー名r ~ユーザー名r/.ssh各権限を変更
1$ sudo chmod -R go-rwx ~ユーザー名/.sshログインチェックのため一旦ログアウト
1$ exit再度ログイン
1$ ssh -i "アプリ名.pem" ユーザー名@割り当てたIPアドレスEC2のアスキーアートが表示されたら作成したユーザーでのSSHログイン完了
※セキュリティ向上のためデフォルトのユーザー「ec2-user」でログインできないようにすると良いみたいです。ログイン後、 $ sudo vi /etc/ssh/sshd_config
で設定ファイルを開き、ファイル末尾に
|
|
を追記し $ sudo service sshd reload
で反映します。
ドキュメントルート領域を作成
var配下にwwwディレクトリを作成
1$ sudo mkdir /var/wwwvarへ移動
1$ cd /var/でオーナーを変更
1$ sudo chown ユーザー名 www
プラグインのインストール
下記コマンドを実行
1$ sudo yum install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel ImageMagick ImageMagick-devel epel-releaseMySQL 5.7 をインストール
123$ sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm$ sudo yum install mysql-devel mysql57 mysql57-serverNode.js 6x をインストール
1$ curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -Yarn をインストール
1$ sudo npm install yarn -grbenv をインストール
1234$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile$ source ~/.bash_profileruby-build をインストール
12$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build$ rbenv rehashRuby 2.3.3 をインストール
1234$ rbenv install -v 2.3.3$ rbenv global 2.3.3$ rbenv rehash$ ruby -v
MySQLをセットアップする
RDSの「インスタンス」から「エンドポイント」を確認し、どこかにコピーしておく
12# こんな感じのやつアプリ名-mysql.cp2gudorjg9e.ap-northeast-1.rds.amazonaws.comEC2の「セキュリティグループ」から作成した項目を選択し、「グループID」をコピー
- 下部のタブの「インバウンド」を選択し、「編集」をクリック
- 「ルールの追加」をクリック、タイプは「MYSQL/Aurora」を選択、ソースに先ほどコピーした「グループID」を入力
- 「保存」
ターミナルからEC2へログインし、MySQLへログイン ※1で取得したエンドポイント値を利用
1$ mysql -h エンドポイント -P 3306 -u root -pパスワードを聞かれたらRDSのパスワードを入力
- MySQLへログインできたらデータベースを確認しておく1234mysql> show databases;# データベース一覧が表示され、アプリ名_production が存在していればOKmysql> exit;
パラメータグループを作成
- RDSの「パラメータグループ」を選択、「パラメータグループの作成」をクリック
- パラメータグループファミリーは「mysql5.7」、グループ名は「アプリ名」、説明は「DB Parameter Group for アプリ名」など
- 「作成」
- 作成したパラメータグループを選択し、「パラメータの編集」をクリック
「フィルタパラメータ」に「character_set」と入力すると照合順序系のパラメータがヒットするので、右上の「パラメータの編集」をクリックし任意の値に設定を変更し保存する
12345character_set_client utf8mb4character_set_connection utf8mb4character_set_database utf8mb4character_set_results utf8mb4character_set_server utf8mb4「フィルタパラメータ」から「skip-character-set-client-handshake」を検索して値を変更する
1skip-character-set-client-handshake 1
STEP5 Railsアプリをデプロイする
GitHubにあるRailsアプリをEC2のNginxへデプロイします。
GitHubと連携する
Gitの設定ファイルを編集
1$ vi ~/.gitconfig以下を追記して保存
12345678910[user]name = Githubのユーザー名email = Githubに登録しているメールアドレス[color]ui = true[url "github:"]InsteadOf = https://github.com/InsteadOf = git@github.com:鍵を作成、鍵名は「aws_git_rsa」、パスワードは空欄
1234$ cd$ chmod 700 .ssh$ cd .ssh$ ssh-keygen -t rsa設定ファイルを作成
1$ vi config以下を追記して保存
1234Host githubHostname github.comUser gitIdentityFile ~/.ssh/aws_git_rsa鍵の内容を確認。どこかにコピーしておく
1$ cat aws_git_rsa.pubGitHubへブラウザからアクセス、「Settings」の「SSH and GPG keys」を選択
- 「New SSH key」をクリック、Titleに「アプリ名 - EC2」、Keyに「先ほど作成した鍵の内容」を入力し「Add SSH key」で登録
ターミナルへ戻り設定ファイルの権限を変更
1$ chmod 600 configGitHubへの接続確認。途中の質問にはYesで。Githubのユーザー名が出てくれば成功
123$ ssh -T github# Hi Githubのユーザー名! You've successfully authenticated, but GitHub does not provide shell access.
アプリケーション格納用の領域を作成
- www配下にRailsアプリを格納するディレクトリを作成12345$ cd /$ sudo chown ユーザー名 var$ cd /var/www/$ sudo mkdir projects$ sudo chown ユーザー名 projects
GitHubからRailsアプリをクローン
作成したprojectsへ移動
1$ cd /var/www/projectsbundlerをインストール
1$ gem install bundlerGemfileを作成
1$ bundle initGemfileを編集
1$ vim GemfileRailsバージョンを記載
1gem "rails", '5.1.4'vendor/bundleへgemをインストール
1234$ bundle install --path vendor/bundle --jobs=4$ bundle exec rails -v# Rails 5.1.4GitHubからアプリをクローン
1234$ git clone git@github.com:GitHubのユーザー名/リポジトリ名.git$ ls# リポジトリ名 Gemfile Gemfile.lock vendorクローンしたディレクトリへ移動
1$ cd リポジトリ名/gemインストール
1$ bundle install --path vendor/bundleシークレットを生成し、どこかにコピーしておく
1$ bundle exec rake secret.bash_profileを編集する
1$ sudo vi ~/.bash_profileRailsの環境変数として先ほどのシークレットを末尾に記載する
1export SECRET_KEY_BASE="生成したシークレットの値"正しく設定されているか確認
123$ echo $SECRET_KEY_BASE# 生成したシークレットの値が表示される
nginxの設定
設定ファイルを作成
1$ sudo vi /etc/nginx/conf.d/アプリ名.conf以下をまるっとコピペし、IPアドレスやアプリ名を記述して保存 ※IPアドレスがわからない場合はEC2のインスタンスの説明から確認可能
1234567891011121314151617181920212223242526272829303132333435upstream unicorn_server {server unix:/var/www/projects/アプリ名/tmp/sockets/.unicorn.sockfail_timeout=0;}server {listen 80;client_max_body_size 4G;server_name IPアドレス;keepalive_timeout 5;# Location of our static filesroot /var/www/projects/アプリ名/public;location ~ ^/assets/ {root /var/www/projects/アプリ名/public;}location / {proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $http_host;proxy_redirect off;if (!-f $request_filename) {proxy_pass http://unicorn_server;break;}}error_page 500 502 503 504 /500.html;location = /500.html {root /var/www/projects/アプリ名/public;}}Nginxを再起動
1$ sudo service nginx restart
Unicornの設定
GitHubのリポジトリの方にも反映したほうが良いかも。
Gemfileを編集
1$ vim Gemfile以下を末尾に追記して保存
123group :production dogem 'unicorn'endUnicornをインストール
1$ bundle installUnicornの設定ファイルを作成
1$ vim config/unicorn.conf.rb以下をまるっとコピペし、アプリ名を記述して保存
1234567891011121314151617181920212223242526272829303132# set lets$worker = 2$timeout = 30$app_dir = "/var/www/projects/アプリ名"$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 configworker_processes $workerworking_directory $app_dirstderr_path $std_logstdout_path $std_logtimeout $timeoutlisten $listenpid $pid# loading boosterpreload_app true# before starting processesbefore_fork do |server, worker|defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!old_pid = "#{server.config[:pid]}.oldbin"if old_pid != server.pidbeginProcess.kill "QUIT", File.read(old_pid).to_irescue Errno::ENOENT, Errno::ESRCHendendend# after finishing processesafter_fork do |server, worker|defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connectionend権限を変更
1$ sudo chmod -R 775 /var/lib/nginx/.bash_profileを編集する
1$ sudo vi ~/.bash_profileRailsの環境変数としてproduction用のデータベース情報を追記して保存
12345export DB_NAME="アプリ名_production"export DB_USERNAME="RDSのユーザー名"export DB_PASSWORD="RDSのパスワード"export DB_HOSTNAME="RDSのエンドポイント"export DB_PORT="3306"正しく設定されているか確認
1234567$ echo $DB_NAME$ echo $DB_USERNAME$ echo $DB_PASSWORD$ echo $DB_HOSTNAME$ echo $DB_PORT# 登録したデータベース情報の値が表示されるmysqldを起動
1$ sudo service mysqld startマイグレーションを実行
1$ bundle exec rake db:migrate RAILS_ENV=production
STEP6 ロードバランサーを設定する
Elastic Load Balancing を利用してロードバランサーの設定を行います。
- EC2の「ロードバランサー」から「ロードバランサーの作成」をクリック
- Classic Load Balancerで「作成」
- ロードバランサー名に「アプリ名-ELB」、ロードバランサーをを作成する場所に「VPCforアプリ名」
- 利用可能なサブネットの「アクション」の「+」マーク2つをクリックして選択済みへ移動させ、「次の手順」をクリック
- セキュリティグループは「アプリ名-SecurityGroup」を選択し「次の手順」
- セキュリティ設定の構成は何もせず「次の手順」
- ヘルスチェックの設定はpingパスを「/」、間隔を「10」、正常のしきい値を「5」に設定し、「次の手順」 ※他はデフォルトでOK
- EC2インスタンスの追加は作成したインスタンスを選択し「次の手順」
- タグの追加ではキーに「Name」、値に「アプリ名-Webserver」と入力
- 「確認と作成」からの「作成」からの「閉じる」
- 一覧画面から作成したロードバランサーを選択し、下部のタブの「インスタンス」をクリック、状態が「InService」なら完了。「OutOfService」の場合は何か問題がある
STEP7 Railsアプリの起動
長い長い工程を経てやっとアプリの起動です。
EC2へSSHでログインし、Railsアプリをプリコンパイルする
1$ bundle exec rake assets:precompile RAILS_ENV=productionNginxを再起動
1$ sudo service nginx restartUnicornを起動
1bundle exec unicorn_rails -c /var/www/projects/アプリ名/config/unicorn.conf.rb -D -E productionUniconの起動を確認
123$ ps -ef | grep unicorn | grep -v grep# プロセスのリストが3行程表示されればOKブラウザからIPを叩いてアクセス ※IPアドレスがわからない場合はEC2のインスタンスの説明から確認可能
1http://IPアドレス/Railsアプリが無事動作すれば成功
参考
初心者向け:AWS(EC2)にRailsのWebアプリをデプロイする方法 目次
というかほぼそのまんまです。
初心者でも構築することが出来ました、丁寧なご説明本当にありがとうございます
※当記事では一部バージョンの変更や手順の省略を行っております
その他
- だいたいイチから作業で6時間くらい掛かった
- Elastic Beanstalk 使えば最初の工程をすっ飛ばして heroku 感覚でデプロイできるっぽい
- EC2インスタンスログイン後、exitせずにターミナルを強制終了してしまった際にログインできなくなってしまった。必ず接続はexitで終了するように
- 環境変数は
.bash_profile
に書くのが正解なのかどうかは分からない - 使ってないインスタンスは停止しておくべし
次回
Route53を利用した独自ドメイン周りの設定をメモります。
はー疲れた。