詳しい概念や、説明はさておき、とにかくRailsアプリをAWSにデプロイする方法を解説します。
EC2の設定
リージョンの確認
右上のサポートの横が東京になっていればOKです。
EC2インスタンスの作成
EC2をクリックして
画面下部のインスタンスを起動をクリック
AMIを選択
「 Amazon Linux 2 AMI 」という、AWSが独自にカスタマイズしたAMIを利用
多分一番上です。
インスタンスタイプは無料枠で使用できる「t2.micro」を選択して、「確認と作成」をクリック
次の画面では「起動」をクリック
キーペアの作成
起動をクリックするとキーペアの選択画面になります。
キーペアはアプリごとに作成しても良いし、一つだけでも良いですが、アプリごとに作成する方法で解説します。
新しいキーペアの作成を選択してキーペア名を入力。
そしてキーペアのダウンロードをしてください。
注意点はこのpemファイルは絶対に削除しないこと。
キーペア名はスペースを含めないこと。
インスタンスの確認
インスタンス名をクリックして、インスタンスIDをコピーしておきましょう。
Elastic IPの作成
左側のメニューからElastic IPを選択
右上のElastic IPの割り当てをクリック
画面が遷移したら、「Amazon の IPv4 アドレスプール」にチェックが入ってることを確認。
確認後、「割り当て」をクリック。
Elastic IPの紐付け
先ほどの画面の右上からアクションをクリック
表示されたプルダウンから「Elastic IP アドレスの関連付け」を選択
先ほどメモしたインスタンスIDを選択
あとは空欄で関連付けるをクリック
先ほどは空欄だったElastic IPにアドレスが割り当てられてます。
EC2の設定変更
立ち上げたばかりのEC2はsshでしか接続できない。
HTTP通信では接続できないので、サーバーとして使用する場合はHTTP通信を許可するためにポートの開放が必要。
そのための設定変更をします。
セキュリティグループのポートを設定
インスタンスの概要の下部のセキュリティをクリック
セキュリティグループをクリック
インバウンドルールの右上のEdit~をクリック
これで設定が完了
EC2インスタンスへログイン
ターミナル
% cd ~
% mkdir ~/.ssh
# .sshというディレクトリを作成
% mv Downloads/ダウンロードした鍵の名前.pem .ssh/
# mvコマンドで、ダウンロードしたpemファイルを、ダウンロードディレクトリから、.sshディレクトリに移動します。
% cd .ssh/
% ls
# pemファイルが存在するか確認しましょう
% chmod 600 ダウンロードした鍵の名前.pem
% ssh -i ダウンロードした鍵の名前.pem ec2-user@作成したEC2インスタンスに紐付けたElastic IP
これで
% ssh -i aws_key.pem ec2-user@52.68.~~~~~~
The authenticity of host '52.68.~~~~~~ (52.68.~~~~~~)' can't be established.
RSA key fingerprint is eb:7a:bd:e6:aa:da:~~~~~~~~~~~~~~~~~~~~~~~~.
Are you sure you want to continue connecting (yes/no)?
(ここで「yes」を入力し、実行する)
この画像になればOK
設定に必要なツールのインストール
ターミナルで下記を実行
[ec2-user@ip-172-31-25-*** ~]$ sudo yum -y update
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
EC2上でJavaScriptを動かす設定
[ec2-user@ip-172-31-25-189 ~]$ sudo curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nodejs
Yarnのインストール
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install wget
[ec2-user@ip-172-31-25-189 ~]$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install yarn
rbenvとruby-buildをインストール
# ①rbenvのインストール
[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
# ②パスを通す
[ec2-user@ip-172-31-25-189 ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# ③rbenvを呼び出すための記述
[ec2-user@ip-172-31-25-189 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# ④.bash_profileの読み込み
[ec2-user@ip-172-31-25-189 ~]$ source .bash_profile
# ⑤ruby-buildのインストール
[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
# ⑥rehashを行う
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
Rubyのインストール
# Ruby 2.6.5のバージョンをインストール
[ec2-user@ip-172-31-25-189 ~]$ rbenv install 2.6.5
# EC2インスタンス内で使用するRubyのバージョンを決める
[ec2-user@ip-172-31-25-189 ~]$ rbenv global 2.6.5
# rehashを行う
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
# Rubyのバージョンを確認
[ec2-user@ip-172-31-25-189 ~]$ ruby -v
バージョンはお使いのバージョンに合わせてください。
データベース
MariaDBを起動
「MariaDB」とは、MySQLの派生として開発されているオープンソースソフトウェアです。MySQLとの互換性があります。
基本的にMariaDBとMySQLは同様のものと考えていただいて差し支えありません。
MariaDBをインストール
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install mariadb-server mysql-devel
データベースの起動
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl start mariadb
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl status mariadb
#起動したか確認するコマンド
「active (running) 」と緑色の表示がされれば、データベースの起動は成功
データベースのrootパスワードの設定
[ec2-user@ip-172-31-25-189 ~]$ sudo /usr/bin/mysql_secure_installation
ここでやること
- Enter current password for root (enter for none): 」と表示されたらEnterキーを押す
- 「Set root password? [Y/n]」と表示されたら「Y」を入力してEnterキーを押す
- 「New password:」と表示されたら自身で決めたパスワードを入力(※とくに画面には何も表示されません)
- 「Re-enter new password:」と表示されたら、同じパスワードを入力
- 「... Success!」と表示されればパスワードの設定自体は完了
- 「Remove anonymous users? [Y/n]」と表示されたら「Y」を入力してEnterキーを押す
- 「Disallow root login remotely? [Y/n]」と表示されたら「Y」を入力してEnterキーを押す
- 「Remove test database and access to it? [Y/n]」と表示されたら「Y」を入力してEnterキーを押す
- 「Reload privilege tables now? [Y/n]」と表示されたら「Y」を入力してEnterキーを押す
これでOKです。
EC2上でRailsを起動
EC2サーバーのssh鍵のペアを作成し、GitHubにssh鍵を登録
[ec2-user@ip-172-31-23-189 ~]$ ssh-keygen -t rsa -b 4096
#途中で「passphrase」など3段階ほど入力を求められることがありますが、すべて何も入力せずにEnterキーを押して進んでください。
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
The key fingerprint is:
3a:8c:1d:d1:a9:22:c7:6e:6b:43:22:31:0f:ca:63:fa ec2-user@ip-172-31-23-189
The key's randomart image is:
+--[ RSA 4096]----+
| + |
| . . = |
| = . o . |
| * o . o |
|= * S |
|.* + . |
| * + |
| .E+ . |
| .o |
+-----------------+
ssh公開鍵の値を確認し、GitHubに登録
[ec2-user@ip-172-31-23-189 ~]$ cat ~/.ssh/id_rsa.pub
#実行結果
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLwt......
この実行結果を全てコピーしてください
コピーした公開鍵をGitHubに登録
このリンクの右上のNew SSHから追加できます。
タイトルは空欄でもOKですが、複数アプリ作るなら任意の名前をつけてください。
その下の欄に先ほどコピーしたSSH公開鍵を登録してください。
Githubで設定がきちんと反映されているか確認しましょう。
[ec2-user@ip-172-31-23-189 ~]$ ssh -T git@github.com
Hi <Githubユーザー名>! You've successfully authenticated, but GitHub does not provide shell access.
#途中でこのまま続けるかどうか、「Yes/No」または「y/n」などの選択肢で聞かれることがあります。
その場合は「Yes」または「y」を入力をし、Enterキーを押下して進んでください。
アプリケーションサーバーの設定
今回はUnicornを使用します。
rails sとローカルサーバーを立ち上げるときにログにpumaと出ると思いますが、これがアプリケーションサーバーです。
で、当然EC2上でもアプリケーションサーバーを設定しなければいけません。
そこで使用するのがUnicornです。
Unicornのインストール
group :production do
gem 'unicorn', '5.4.1'
end
でいつも通りbundle install
「config/unicorn.rb」を作成
#サーバ上でのアプリケーションコードが設置されているディレクトリを変数に入れておく
app_path = File.expand_path('../../', __FILE__)
#アプリケーションサーバの性能を決定する
worker_processes 1
#アプリケーションの設置されているディレクトリを指定
working_directory app_path
#Unicornの起動に必要なファイルの設置場所を指定
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"
#Railsアプリケーションの応答を待つ上限時間を設定
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
そのままコピペでOKです。
リモートリポジトリに「commit→push」
EC2上にリポジトリの情報を反映
#mkdirコマンドで新たにディレクトリを作成
[ec2-user@ip-172-31-23-189 ~]$ sudo mkdir /var/www/
#作成したwwwディレクトリの権限をec2-userに変更
[ec2-user@ip-172-31-23-189 ~]$ sudo chown ec2-user /var/www/
GitHubから「リポジトリURL」を取得
[ec2-user@ip-172-31-23-189 ~]$ cd /var/www/
[ec2-user@ip-172-31-23-189 www]$ git clone コピーしたURLを貼り付ける
これでエラーが出なければOK
EC2の能力を拡張
Swapファイルの領域を広げます。
「Swapファイル」とは、メモリの容量を一時的に増やすために準備されるファイルのことです。
# ホームディレクトリに移動
[ec2-user@ip-172-31-25-189 ~]$ cd
[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
# しばらく待って、以下のように表示されれば成功です(処理に時間がかかります)
512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 7.35077 秒、 73.0 MB/秒
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1
# 以下のように表示されれば成功
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1 none swap sw 0 0" >> /etc/fstab'
EC2内でgemをインストール
# クローンしたディレクトリに移動
[ec2-user@ip-172-31-23-189 www]$ cd /var/www/開発中のアプリケーション
# rubyのバージョンを確認
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
ローカルで開発してきたアプリケーションでどのバージョンのbundlerが使われていたのか確認
# 開発中のアプリケーションのディレクトリで実行
% bundler -v
Bundler version 2.1.4
# 「2.1.4」の箇所は、ローカルで確認したbundlerのバージョンを導入します
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ gem install bundler -v 2.1.4
# 以下のコマンドは、処理に数分以上かかる場合があります
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle install
環境変数を設定
secret_key_baseを作成
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rake secret
69619d9a75b78f2e1c87ec5e07541b42f23efeb6a54e97da3723de0.....
出力結果はどこかにメモしといてください。
[ec2-user@ip-172-31-23-189 ~]$ sudo vim /etc/environment
何も表示されない画面に変わると思うので、「i」を入力して挿入モードにする
DATABASE_PASSWORD='先ほど設定したパスワード'
SECRET_KEY_BASE='rake secretの出力結果'
AWS_ACCESS_KEY_ID='ご自身のアクセスキー'
AWS_SECRET_ACCESS_KEY='ご自身のシークレットキー'
#その他環境変数に設定したいキーがあれば入力してください。
自分はGoogleのAPIを使用しているので、Googleを付け加えました。
[ec2-user@ip-172-31-23-189 ~]$ exit
一度ログアウト
$ ssh -i [ダウンロードした鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
#環境変数が設定されているか確認
[ec2-user@ip-172-31-23-189 ~]$ env | grep SECRET_KEY_BASE
#こんな感じで確認してください。
ポートを解放
セキュリティグループのポートを設定
AWSのインスタンスの詳細画面で、画面下部のセキュリティをクリックして、セキュリティグループのリンクをクリック
インバウンドルールの右上のEdit~をクリック
タイプ:カスタムTCP
プロトコル:TCP
ポート範囲:3000
送信元:カスタム/0.0.0.0/0
Railsを起動
本番環境でRailsを起動
production:
<<: *default
database: #編集しない
#下記を編集
username: root
password: <%= ENV['DATABASE_PASSWORD'] %>
socket: /var/lib/mysql/mysql.sock
Githubでマスターをマージして
[ec2-user@ip-172-31-23-189 <リポジトリ名>] git pull origin master
DBの作成とマイグレーション、Railsの起動
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:create RAILS_ENV=production
Created database '<データベース名>'
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails db:migrate RAILS_ENV=production
#もしここで
「Mysql2::Error: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'」
というエラーが起こった場合、データベースが起動していない可能性がある
「sudo systemctl start mariadb」というコマンドをターミナルから打ち込み、mysqlの起動を試してみましょう。
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
アセットファイルのコンパイル
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ rails assets:precompile RAILS_ENV=production
Railsの再起動が必要なので、Railsを再起動する
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
#出力結果
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto
unicorn
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill <確認したunicorn rails masterのプロセスid>
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
RAILS_SERVE_STATIC_FILES=1でRailsがコンパイルされたアセットを見つけられるように指定する役割があります。
このコマンドを実行したときにエラーが出ることがあります。
エラーの内容次第ですが、パターンは3つになります。
①rbenvをrehash
rbenv rehash
②Githubにマージされてない
マージした後に
git push -u origin master
③master failed to start, check stderr log for detailsと出た
ログを見ましょう
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ less log/unicorn.stderr.log
これを実行するとファイル名が並ぶので、
「一番下から最新のログ」を確認する。
アクセスする
http://<Elastic IP>:3000/
にアクセスすると、無事表示されます。
WEBサーバーの設定
Nginxを導入
[ec2-user@ip-172-31-25-189 ~]$ sudo amazon-linux-extras install nginx1
Is this ok [y/d/N]:と出てきたら、yを選択して決定
Nginxの設定ファイルを編集
[ec2-user@ip-172-31-25-189 ~]$ sudo vim /etc/nginx/conf.d/rails.conf
ファイルが開けたら「i」を押して、インサートモードにします。
upstream app_server {
# Unicornと連携させるための設定
server unix:/var/www/リポジトリ名/tmp/sockets/unicorn.sock;
}
# {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
server {
# このプログラムが接続を受け付けるポート番号
listen 80;
# 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない
server_name Elastic IP;
# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
client_max_body_size 2g;
# 接続が来た際のrootディレクトリ
root /var/www/リポジトリ名/public;
# assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
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;
}
リポジトリ名とElastic IPはご自身のものに変更してください。
[ec2-user@ip-172-31-25-189 ~]$ cd /var/lib
[ec2-user@ip-172-31-25-189 lib]$ sudo chmod -R 775 nginx
[ec2-user@ip-172-31-25-189 lib]$ cd ~
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl reload nginx
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl start nginx
これで設定変更が完了です!
Unicornの設定を変更
(省略)
listen 3000
(省略)
listen "#{app_path}/tmp/sockets/unicorn.sock"
こちらに変更して、commitしてpushしてください。
# 開発中のアプリケーションに移動
[ec2-user@ip-172-31-25-189 ~]$ cd /var/www/開発中のアプリケーション
# GitHubの内容をEC2に反映させる
[ec2-user@ip-172-31-23-189 <レポジトリ名>]$ git pull origin master
#Unicornの再起動
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ ps aux | grep unicorn
#killするプロセスIDを確認
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ kill プロセスID
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
ここまで完了したら
http://<Elastic IP>
にアクセスする
これで手動デプロイの完了です。