はじめに
数ヶ月前に書いたRails5のAWS構築をもう少し項目を増やしてから公開しようと思っていたのですが、なかなか出来ないのでもう公開します。(ELBとかCloudFlontとかもっとちゃんと書けそう、、)
項目の追加や修正は適宜入れると思います。
Railsは5.0を使っています。(記事を書いたときの最新)
4系は以前書きました↓
- AWS VPCによるネットワーク構築とEC2によるサーバー構築
- RailsアプリケーションのAWSによる公開|unicorn + nginx
- AWS RailsアプリケーションのCapistranoによるデプロイ
構築する環境
- VPC
- EC2
- Nginx + Puma
- Capistrano
- (S3)
- ELB
- RDS
- CloudFlont
- Route53
- (CloudWatch)
VPC、EC2のインスタンスの作成
AWSのデザインが多少変更はありますが、以下を参考に作成出来ます。
AWS VPCによるネットワーク構築とEC2によるサーバー構築
これに追加でElastic IPの設定もしておきました。
EC2内の環境構築
作成したEC2にログインして環境を構築します。
ec2-userでまずログインしましょう。
ユーザーの作成
デフォルトではec2-userなので新たなユーザーを追加し、そのユーザーでsshログイン出来るように設定します。
$ sudo adduser shizuma #ユーザーの追加 「shizuma」の部分は好きなユーザー名にします。以後「shizuma」の部分は各自のユーザー名になります。
$ sudo passwd shizuma
#ここで、新規ユーザーのパスワードを設定します。
$ sudo visudo
-----------------------------
#vimが起動するので新規ユーザーにroot権限を与える。
root ALL=(ALL) ALL
shizuma ALL=(ALL) ALL #この行を追加
-----------------------------
$ sudo su - shizuma #ユーザー切り替え
#先ほど設定したパスワード
ここでローカルに一旦戻り、鍵を作成します。
$ cd .ssh
$ ssh-keygen -t rsa
-----------------------------
Enter file in which to save the key ():first_aws_rsa #ここでファイルの名前を記述して、エンター
Enter passphrase (empty for no passphrase): #何もせずそのままエンター
Enter same passphrase again: #何もせずそのままエンター
-----------------------------
$ vi config
-----------------------------
# 以下を追記
Host first_aws
Hostname 54.64.22.197 #自分の設定に合わせて
Port 22
User shizuma #先ほどのユーザー名
IdentityFile ~/.ssh/first_aws_rsa #秘密鍵の設定
-----------------------------
次に、サーバーに戻り作成した 公開鍵
をサーバーに設定します。
$ mkdir .ssh
$ chmod 700 .ssh
$ cd .ssh
$ vi authorized_keys
-----------------------------
#localの「first_aws_rsa.pub」の中身のコピペ。(localで $ cat first_aws_rsa.pubとかすると良い)
ssh-rsa sdfjerijgviodsjcIKJKJSDFJWIRJGIUVSDJFKCNZKXVNJSKDNVMJKNSFUIEJSDFNCJSKDNVJKDSNVJNVJKDSNVJKNXCMXCNMXNVMDSXCKLMKDLSMVKSDLMVKDSLMVKLCA shizuma@shizuma-no-MacBook-Air.local
-----------------------------
$ chmod 600 authorized_keys
$ exit
$ exit
これで設定が完了したので、以降作成したユーザーでアクセスするようにします。
基本ライブラリとrubyの環境構築
$ 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 \
mysql mysql-server mysql-devel \
ImageMagick ImageMagick-devel \
epel-release
$ sudo yum install nodejs npm --enablerepo=epel
$ 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_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv rehash
$ rbenv install -v 2.3.1
$ rbenv global 2.3.1
$ rbenv rehash
$ ruby -v
gitの設定
最低限の設定だけしておきます。
$ vi .gitconfig
[user]
name = your_name #自分の名前
email = hoge@hoge.com #自分のメアド
[alias] #これはお好きに
a = add
b = branch
ch = checkout
st = status
[color] #色付け
ui = true
[url "github:"] #pull、pushのための設定
InsteadOf = https://github.com/
InsteadOf = git@github.com:
アプリケーションフォルダの設置
/var/www/rails
にアプリケーションフォルダを設置します。
$ cd /
$ sudo mkdir -p /var/www/rails
$ sudo chown -R shizuma var/www
GitHubの接続とアプリケーションのclone
$ cd ~/.ssh
$ ssh-keygen -t rsa
-----------------------------
Enter file in which to save the key ():aws_git_rsa #ここでファイルの名前を記述して、エンター
Enter passphrase (empty for no passphrase): #何もせずそのままエンター
Enter same passphrase again: #何もせずそのままエンター
-----------------------------
$ chmod 744 config
$ vi config
-----------------------------
# 以下を追記
Host github github.com
Hostname github.com
User git
Port 22
IdentityFile ~/.ssh/aws_git_rsa #秘密鍵の設定
-----------------------------
$ cat aws_git_rsa.pub
-----------------------------
ssh-rsa sdfjerijgviodsjcIKJKJSDFJWIRJGIUVSDJFKCNZKXVNJSKDNVMJKNSFUIEJSDFNCJSKDNVJKDSNVJNVJKDSNVJKNXCMXCNMXNVMDSXCKLMKDLSMVKSDLMVKDSLMVKLCA shizuma@ip-10-0-1-10
-----------------------------
ここで、これをコピペしてgithubに公開鍵を登録する。
githubへの鍵の登録がよくわからない方は以下の記事を参考に。
gitHubでssh接続する手順~公開鍵・秘密鍵の生成から~
そして、git clone する。
$ cd /var/www/rails
$ git clone https://github.com/kuboshizuma/cheerfull # 自分のアプリケーション
RDSの設定
EC2の環境構築に一区切りついたのでRDSの設定を行います。
DBサブネットの登録
RDSで使うサブネットを登録します。
この設定には異なるアベイラビリティゾーンにあるサブネットが最低1つずつ計2つ必要になります。
また、Railsアプリケーションをおいたサブネットはゲートウェイに繋がったpublicなサブネットなので、privateなサブネットを異なるアベイラビリティゾーンに一つずつ作成します。
パラメータグループの設定
パラメータグループを設定します。
mysql
を使用していると設定なので、ここではmysqlを選択します。バージョンは適宜選択。
「chara...」で検索すると出て来るcharasetをutf-8
に変更。
設定が完了した後に、パラメータの編集を押してパラメーター変更。
セキュリティグループの作成
VPCでセキュリティグループを作成します。
インバウンドルールにMySQL
を設定し、MySQLのアクセスのみ許可します。
「送信元」は0.0.0.0/0
で設定。特定のRailsアプリケーションサーバーがあるサブネットに限定するほうがよさそう。
RDSインスタンスの作成
エンジンの選択
本番稼働用?
DB詳細設定の指定
無料枠はt2.micro
詳細設定の設定
各種作成したもので設定。
接続確認
hostは各自の作成したRDSインスタンスのエンドポイントをみる。
$ mysql -h hogepoge.ap-northeast-1.rds.amazonaws.com -u shizuma -P 3306 -p
接続出来たら完了!
絵文字の扱い
絵文字も登録出来るようにする場合。
以下を参考に utfmb4
を採用する。
MAMPでは /Applications/MAMP/conf/my.cnf
にmy.cnf
を設置した。
Railsアプリケーションの起動のための準備
puma setting
以下を追記する。
# add setting for production
_proj_path = "#{File.expand_path("../..", __FILE__)}"
_proj_name = File.basename(_proj_path)
_home = ENV.fetch("HOME") { "/home/#{ENV['PUMA_USER']}" }
pidfile "#{_home}/run/#{_proj_name}.pid"
bind "unix://#{_home}/run/#{_proj_name}.sock"
directory _proj_path
# add end
ENV['PUMA_USER']
にサーバーのユーザー名が入るように環境変数を設定。
database setting
以下のように編集。
production:
<<: *default
database: cheerfull
username: <%= ENV['DATABASE_USER_NAME_PRODUCTION'] %>
password: <%= ENV['DATABASE_PASSWORD_PRODUCTION'] %>
host: <%= ENV['DATABASE_HOST_PRODUCTION'] %>
それぞれ該当の環境変数を設定。
rake secret
以下のsecret keyの箇所に値が入るように環境変数を設定。
rake secret
とコマンドを打つと出て来る文字列を設定する。
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
$ gem install bundler
$ bundle install
$ rake db:create RAILS_ENV=production
$ rake db:migrate RAILS_ENV=production
PumaとNginxの起動
Pumaの起動
アプリケーションディレクトリにて以下を実行。
$ RAILS_SERVE_STATIC_FILES=true RAILS_ENV=production puma -w 4
「Ctr+c」でプロセス消さなければ生き残る。
プロセス消す必要があれば以下のようにする。
$ ps aux | grep puma # プロセスIDを探す
$ kill -9 (ID)
Nginx の起動
「cheerfull」の部分は自分のアプリケーションディレクトリ名に変更する。
# log directory
error_log /var/www/rails/cheerfull/log/nginx.error.log;
access_log /var/www/rails/cheerfull/log/nginx.access.log;
upstream app_server {
# for UNIX domain socket setups
server unix:/home/shizuma/run/cheerfull.sock fail_timeout=0;
}
server {
listen 80;
server_name 12.134.156.178; # 自分のIP
# nginx so increasing this is generally safe...
# path for static files
root /var/www/rails/cheerfull/public;
# page cache loading
try_files $uri/index.html $uri @app_server;
location / {
# HTTP headers
proxy_pass http://app_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/rails/cheerfull/public;
}
client_max_body_size 4G;
keepalive_timeout 5;
}
ユーザーをnginxから自分のユーザー名に変更しておく。
#user nginx;
user shizuma;
nginxを起動します。
$ sudo service nginx restart
これで、IPアドレスでアクセスするとアプリケーションが表示されるようになりました。
Capistranoの設定
諸々動くことが確認出来たのでデプロイが出来るように設定します。
デプロイのためにCapistranoの設定をします。
慣れてきたら、いきなりCapistranoの設定をしていけばいいと思います。
socketの場所もアプリケーションディレクトリに変更するのでnginxの設定もそれに合わせて変更します。
「cheerfull」の部分は自分のアプリケーション名に変更する。
require 'dotenv'
Dotenv.load
lock "3.7.1"
set :application, "cheerfull"
set :repo_url, "git@github.com:your_gitname/cheerfull.git"
set :branch, 'master'
set :deploy_to, '/var/www/rails/protospacce'
set :linked_files, fetch(:linked_files, []).push('.env')
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :keep_releases, 5
set :rbenv_ruby, '2.3.1'
# puma setting
set :puma_threads, [4, 16]
set :puma_workers, 0
set :pty, true
set :use_sudo, false
set :stage, :production
set :deploy_via, :remote_cache
set :deploy_to, "/var/www/rails/#{fetch(:application)}"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{shared_path}/log/puma.error.log"
set :puma_error_log, "#{shared_path}/log/puma.access.log"
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true
namespace :deploy do
desc 'Create database'
task :db_create do
on roles(:db) do |host|
with rails_env: fetch(:rails_env) do
within current_path do
execute :bundle, :exec, :rake, 'db:create'
end
end
end
end
end
実際にdeployする前に、共有ファイルは用意しておきましょう。この場合、.env
。
ここでpumaのセッティングをしたので、config/puma.rb
はもう不要になります。
また、dotenvを使用する場合は変更を読み込むために config/deploy/templates/puma.rb.erb
を用意します。以下を用意。
#!/usr/bin/env puma
directory '<%= current_path %>'
rackup "<%=fetch(:puma_rackup)%>"
environment '<%= fetch(:puma_env) %>'
<% if fetch(:puma_tag) %>
tag '<%= fetch(:puma_tag)%>'
<% end %>
pidfile "<%=fetch(:puma_pid)%>"
state_path "<%=fetch(:puma_state)%>"
stdout_redirect '<%=fetch(:puma_access_log)%>', '<%=fetch(:puma_error_log)%>', true
threads <%=fetch(:puma_threads).join(',')%>
<%= puma_bind %>
<% if fetch(:puma_control_app) %>
activate_control_app "<%= fetch(:puma_default_control_app) %>"
<% end %>
workers <%= puma_workers %>
<% if fetch(:puma_worker_timeout) %>
worker_timeout <%= fetch(:puma_worker_timeout).to_i %>
<% end %>
<% if puma_preload_app? %>
preload_app!
<% else %>
prune_bundler
<% end %>
on_restart do
puts 'Refreshing Gemfile'
ENV["BUNDLE_GEMFILE"] = "<%= fetch(:bundle_gemfile, "#{current_path}/Gemfile") %>"
ENV.update Dotenv::Environment.new('.env')
end
<% if puma_preload_app? and fetch(:puma_init_active_record) %>
before_fork do
ActiveRecord::Base.connection_pool.disconnect!
end
on_worker_boot do
ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.establish_connection
end
end
<% end %>
$ bundle exec production cap puma:config
これでこの設定を本番に反映。
あとはデプロイコマンドを打つ。
$ bundle exec cap production deploy
デプロイdone!
nginxのlogの位置やsocketの位置を変更します。
# log directory
error_log /var/www/rails/cheerfull/shared/log/nginx.error.log;
access_log /var/www/rails/cheerfull/shared/nginx.access.log;
upstream app_server {
# for UNIX domain socket setups
server unix:/var/www/rails/cheerfull/shared/tmp/sockets/cheerfull-puma.sock fail_timeout=0;
}
server {
listen 80;
server_name 12.134.156.178; # 自分のIP
# nginx so increasing this is generally safe...
# path for static files
root /var/www/rails/cheerfull/current/public;
# page cache loading
try_files $uri/index.html $uri @app_server;
location / {
# HTTP headers
proxy_pass http://app_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/rails/cheerfull/current/public;
}
client_max_body_size 4G;
keepalive_timeout 5;
}
$ sudo service nginx restart
これで、デプロイ環境が整いました。
以前起動したpumaのプロセスはきっておきましょう。
複数サーバーへのデプロイ
multiconfig
を使用します。
gem 'capistrano-multiconfig', '~> 3.1', require: false
Capfileのcapistrano/setup
から変更。
# require "capistrano/setup"
require 'capistrano/multiconfig'
config/deploy/production.rb
から config/deploy/app1/production.rb
に変更する。
以下のようにdeploy出来るようになる。
$ bundle exec cap app1:production deploy
違うサーバーにデプロイするときは同じように config/deploy/app2/production.rb
を準備すればオーケー。
$ bundle exec cap app2:production deploy
これで違うサーバーにデプロイ出来る。
これまでと同様にec2サーバーをもう一度用意して2箇所にデプロイ出来るようにする。
ロードバランサー ELB
ロードバランサーをhttpsで運用したいときadmin@hoge.com
のようなアドレスへのメールを受信可能のしないといけない。
以下でとりあえずzoneファイルのインポートまでする。
Amazon Route53 ネームサーバへの移行手順(お名前.comからの)
その後にこの記事にあるようにお名前.com側の設定をする。
お名前.com + Route53で独自ドメインのメールをGmailに転送する
メールの転送が出来ていることを確認する。
そして、ELBの指示に従って設定。
下記参考。
【初心者向け】ELBにSSL証明書をインストールする
そこまでしたら
Amazon Route53 ネームサーバへの移行手順(お名前.comからの)
の続きでELBとつなげる。
注意点は、ターゲットグループにトラフィックをルーティングするときのプロトコルをHTTPにすること。これでELBへはHTTPSでアクセス出来、それをアプリケーションではHTTPで扱うことが出来る。
また、以下のように nginxのサーバーネームにドメイン名を追加する必要がある。
server_name hogepoge.com 00.000.00.00 sakamichi-app-elb-000000000.ap-northeast-1.elb.amazonaws.com
CloudFront
Amazon CloudFront + ACM 独自ドメインで HTTPS (SSL) 配信設定メモ
CloudWatchとか
必要の応じて加筆。