これまでさくらVPS、appache、passengerでは結構デプロイしてきたけど、AWSの経験がなかったので今回はまったところも含めてメモしておきます。結局、AWSの立ち上げから丸2日間ぐらい悪戦苦闘してしまった。今後はサクサクできるようにしたいです。
全体としてこちらの記事にお世話になりました。
AWSはこれで大丈夫|unicorn + nginx + capistrano + slackistrano のコマンド一覧
最小限でRailsをAWSにデプロイする。Ubuntu,Unicorn,Nginx,PostgreSQL
デプロイの中身を理解するために、capistranoは使用せず手動でデプロイしています。
AWSの設定
AWSの設定は上記で紹介した、AWSはこれで大丈夫|unicorn + nginx + capistrano + slackistrano のコマンド一覧を元に設定したらある程度サクサク進みました。
VPCの設定
VPCというものが何かは正直よくわかっていません。いくつかのネット上の記事を読んだけどインフラ的な概念の基礎知識が欠けているのかどれを読んでもピンと来ず、今後の課題になっています。。。VPCを設定することで自分専用のAWS空間を使用でき、IPアドレスの設定など諸々が出来るようになるという認識ですが間違っていたらコメントください。
VPCの設定はこちらの動画を参考にAWSからぽちぽち設定するだけでした。
AWS講座 - VPC/EC2インスタンスの作成から接続まで
EC2インスタンスの設定
EC2インスタンスの設定も上記の動画を参考にぽちぽち行うだけで完了します。キーペアを~/.sshに保存してあげます。Elastic IPの設定を忘れずに行いましょう。この設定をすることで固有のIPアドレスをEC2インスタンスに紐づけることができます。これやらないとサーバーのIPアドレスが起動の度に変わってしまうようです。
SSHでEC2に接続
ここまででEC2にアクセスする準備が完了しました。ここからSSHでEC2にアクセスして各種設定をコマンドラインから行えるようにします。まずはダウンロードしたキーペアを~/.sshファイルにうつします。下記は全てローカルで実行しています。
mkdir ~/.ssh # sshフォルダがない場合は作成しておく
chmod 700 ~/.ssh # sshフォルダの権限を変更
cd /Downloads # キーペアをダウンロードしたフォルダに移動
mv /Downloads/[appname].pem ~/.ssh/ #.pemと書かれたものがawsアクセスのためのキー
ssh -i ~/.ssh/[appname].pem [ipアドレス] # Elastic IPで設定したアドレスを[ipアドレス]に入力
Are you sure you want to continue connecting(yes/no)?とでたらyesと入力して接続できればOKです。
作業用ユーザーの作成
EC2はデフォルトでec2-userというuserでアクセスしますが、セキュリティを強化するのであれば別のユーザーを作成し、ec2-userを削除しておきましょう。下記は全てsshでログインした先の作業です。ローカルでの作業ではないので注意。
sudo adduser [username] # 任意の[username]でユーザーを作成
sudo usermod -G wheel [username] #userをwheelグループに追加
sudo passwd [username] #userのパスワードを設定
visudo # sudoのファイルを下記の通り、編集
sudo権限を[username]に付与して、sudoで諸々できるように設定しましょう。
%wheel ALL=(ALL) ALL # コメントアウトして有効化する、「/」を押してからwheelと打って検索して該当箇所を探す
ユーザーが作成できて、sudo権限を追加したら、sshでログインするためのauthorized_keysを[username]のフォルダに移動しましょう。
sudo rsync -a ~/.ssh/authorized_keys ~[username]/.ssh/
sudo chown -R [username]:[username] ~[username]/.ssh
sudo chmod -R go-rwx ~[username]/.ssh
ここから一旦ローカルで作業を行い、新しく作成した[username]でsshログインできるか確認しましょう。
ssh -i ~/.ssh/[appname].pem [username]@[ipアドレス]
ec2-userではなく[username]でアクセスできたら完了!ログインできたことを確認したらec2-userを削除しましょう。
sudo userdel ec2-user # ec2-userを削除
作業用ディレクトリの作成
railsアプリを配置する作業用のディレクトリを作成します。多くのアプリが/var/wwwの配下にあるので、その通り作成しています。
sudo mkdir /var/www # /var/wwwディレクトリを作成する
cd /var
sudo chown [username] www # 上記で指定したユーザーを所有者として指定する
Portの変更
sshでアクセスできるポートはデフォルトでは22ですが、これを変更することでセキュリティが強化されるのでやっておきましょう。
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org # 予めsshd_configのファイルをコピーしておき間違っても戻せるようにしておく
sudo vi /etc/ssh/sshd_config # ssh_configを編集する
Port 22 # 念のためPort22でもアクセスできるようにしておき、下記のPortでログインできることを確認してからコメントアウトする
Port 22012 # Port22の下に任意の番号を設定する、ここでは22012を設定
sudo service sshd reload # 変更を反映させるためにsshdを再起動
Portを変更したらAWSのセキュリティグループ設定に上記のポートを追加しておかないとアクセスできません。セキュリティグループの設定からカスタムTCPルールで22012を設定します。変更が終了したらローカルから下記のコマンドでアクセスが可能か確認します。
ssh -i ~/.ssh/[appname].pem -p 22012 [username]@[ipアドレス]
上記のコマンドでアクセスできたら、今度はAWSのサーバー側で下記の作業を行い、22番ポートを閉じてしまいます。
sudo vi /etc/ssh/sshd_config # ssh_configを編集する
#Port 22 # コメントアウトしてPort 22でアクセスできないようにする
Port 22012 # Port22の下に任意の番号を設定する、ここでは22012を設定
22番ポートでアクセスできないか確認するためにはローカルで下記のコマンドを打ってログインできないことを確認すればOKです。
ssh -i ~/.ssh/[appname].pem [username]@[ipアドレス]
プラグインのインストール
下記のコマンドを打って必要なプラグインを全てインストールします。
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 # nodejsをインストール
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.1.3 # version2.1.3をインストール、バージョンは好みで変更
rbenv global 2.1.3
rbenv rehash
ruby -v # 上記のバージョンのrubyがインストールされていることを確認
RDSの設定
データベースを扱うRDSの設定を行っていきます。これも基本的にはぽちぽちやっていくだけです。これはドットインストールを参考にしました。
注意する点としては、DB nameとMaster UsernameとMaster Passwordはrailsからアクセスする際にdatabase.ymlで設定する際に必要になるのでメモを取るなり覚えておきましょう。またエンドポイントというものがRDSの画面にありますが、ここで表示されているエンドポイントもアクセスする際に必要で、database.ymlに記述するのでメモしておきましょう。
RDSでの立ち上げが終了したらセキュリティグループの設定にて、mysqlの3306ポートを開くように設定しておきましょう。設定の際にはこちらを参考にしました。
mysqlの日本語設定
また日本語を使用する場合は、RDSの画面から「パラメーターグループの作成」⇒「パラメーターの編集」から以下のパラメーターを変更する必要があります。
character_set_client :utf8 #デフォルトからutf8に変更
character_set_connection :utf8 #デフォルトからutf8に変更
character_set_database :utf8 #デフォルトからutf8に変更
character_set_results :utf8 #デフォルトからutf8に変更
character_set_server :utf8 #デフォルトからutf8に変更
skip-character-set-client-handshake :1 #0から1に変更
僕はこの日本語の処理を忘れて結構面倒なことになってしまいました。rake db:create、rake db:migrateまでしてしまった後にこの問題に気づいたため、こちらのページを参考に修正しました。
MySQLでcharacter_set_databaseがlatin1になってしまう問題の対応方法
ここまで設定したらEC2からアクセスできるか確認しましょう。
mysql -h [エンドポイントで表示されているもの] -u [設定したMaster Username] -p
Enter Password: #上記で設定したMaster Password
mysqlにアクセスできたら設定は完了、念のため下記のコマンドで指定したDB nameでdatabaseが作成されているか確認しましょう。
mysql > show databases; # 表示されたdatabaseに[DB name]があればOK
nginxの設定
基本的にインストールして、[appname].confの設定ファイルを記述するだけで終わりです。設定については最小限でRailsをAWSにデプロイする。Ubuntu,Unicorn,Nginx,PostgreSQLを参考にコピーして一部変更した感じです。下記のような形にしています。
sudo yum install nginx
sudo vi /etc/nginx/conf.d/[appname].conf # 下記のファイルの通りに編集
upstream unicorn_server {
server unix:/tmp/unicorn.sock
fail_timeout=0;
}
server {
listen 80;
client_max_body_size 4G;
server_name {IPアドレス};
keepalive_timeout 5;
# Location of our static files
root /var/www/{appname}/public; # appname部分は自分自身で設定
location ~ ^/assets/ {
# 誤り) root /var/www/{appname}/shared/public;
root /var/www/{appname}/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/{appname}/public;
}
}
編集が終了したらnginxを起動させます。
sudo service nginx start # nginxを起動
sudo chkconfig nginx on # nginxの自動起動をonに設定しておく
Elastic IPで指定した固定のipアドレスにアクセスしてnginxの表示が出たらOK
gitクローン
gitを使ったデプロイ方法を参考にローカルでプッシュすると本番環境に変更したファイルが置かれるように設定しました。既にgitで管理しており、[appname].gitでgithubで管理しています。
ローカルで ~/.ssh/configファイルを作成
準備として、~/.ssh/configファイルを作成しておきます。このファイルを作成しておくことで簡単なコマンドでsshログインが可能になります。
host [appname] # 上記で指定したappnameと同じものを指定
HostName ***.***.***.** # Elastic IPで指定した固定のipアドレス
Port 22012 # 上記で22012に変更していたのでそのportを指定
User [username] # AWSの最初の設定で作成した[username]を指定
IdentityFile ~/.ssh/id_rsa
この設定を行っておくと、ssh [appname]
でsshログインが可能になります。
作業用ディレクトリに移動してgit cloneする
ssh [appnmae]
cd /var/www
git init --bare [appname].git # [appname].gitで既に管理している場合
プッシュした際にAWSにもpushされるように、ローカルにて/.git/configファイルを下記のように修正します。
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@github:[gituser]/[appname].git
url = [appname]:/var/www/[appname].git
ここまで完了したらローカルでgit push origin master
しましょう。その後AWSの作業用ディレクトリにアクセスしてgit cloneできるか確認します。
ssh [appname]
cd /var/www
git clone /[appname].git
これで/var/wwwに[appname]というrailsアプリ用のディレクトリが作成できているはずです。git pushした際に、AWS側でpullする設定をしたい場合は下記のリンクからgit hookの追加の部分を読んでいただければと思います。
Unicornの設定
ここまでくればもう少しのはずですが、unicornの設定は若干はまりました。working_directoryの設定の際に、/currentの記述をしていなかったらCSSとjavascriptのファイルを読み込まずに3時間ぐらいはまっていました。。。
@app_path = '/var/www/{appname}'
working_directory @app_path + "/current" # このcurrentの指定をしていなかったらデプロイ後に/assets以下が読み込まれずはまった
worker_processes 2
preload_app true
timeout 30
listen "/tmp/unicorn.sock", :backlog => 64
pid "/var/www/{appbane}/shared/tmp/pids/unicorn.pid"
stderr_path "#{@app_path}/log/unicorn.stderr.log"
stdout_path "#{@app_path}/log/unicorn.stdout.log"
before_fork do |server, worker|
ENV['BUNDLE_GEMFILE'] = File.expand_path('Gemfile', ENV['RAILS_ROOT'])
end
before_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
end
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
end
end
end
after_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
end
設定ファイルの記述が終わったらAWS側でunicornを起動させます。
sudo mkdir /var/www/{appname}/shared/tmp/pids # 必要なディレクトリの作成
sudo chmod 777 /var/www/{appname}/shared/tmp/pids # 必要なディレクトリに権限付与
cd /var/www/{appname}
bundle exec unicorn_rails -c config/unicorn.rb -p 8080 -D -E production #起動
ps aux | grep unicorn #動いているかの確認
ここまででunicornの設定は完了。後はbundle installして、rake db:migrateして、rake assets:precompileすればOKです。
migrationおよびassets:precompile
ここまでで必要な設定は終了したので、migrationおよびコンパイル作業をやりましょう。
cd /var/www/[appname]
gem install bundler # bundlerのインストールを行わないとbundleコマンドが使えない
bundle install # gemファイルの必要ファイルが読み込まれる
bundle exec rake db:migrate RAILS_ENV=production # migrationの実行
bundle exec rake assets:precompile RAILS_ENV=production
sudo service nginx restart # nginxの再起動を行う
ここまででipアドレスにアクセスすればちゃんとサイトが表示されるはずです。僕はここまでいった後にサイトが表示されず、nginxの403forbiddenが表示されたり、bad gatewayが表示されたりしたので、上記の設定ファイルを何度か見直したりしました。やっと表示されたと思ってもcssが読み込まれていないなんてこともありました。上記の設定ファイルの変更は失敗を反映しているので大丈夫だと思います。
AWSで独自ドメインの設定
ここまで出来たのでお名前ドットコムで取得した独自ドメインをAWSに紐づけます。独自ドメインの紐付けはそこまで難しくなく、AWSのRoute53をぽちぽち設定して、表示されたものをお名前ドットコムの管理画面で設定すればOKって感じです。僕個人は、お名前ドットコムは技術サポートの電話は24時間対応なので、困ったらちゃんと設定できているか電話で確認してしまっています。
お名前.com で取ったドメインを Amazon Route53で管理し、サブドメインをはてなブログに割り当てるまで
以上になります。結構はまって大変だったので今後もアップする際に必要になるかと思ってメモとして残しておきます。誰かの参考になればうれしいです。
変更の反映 Unicornの再起動
apacheとpassengerの時はapacheを再起動すれば変更が反映されていたので、nginxの再起動で反映されるかと思いきや反映されていなかったのでメモ。