Help us understand the problem. What is going on with this article?

RailsアプリをAWS、unicorn、nginxで手動デプロイして独自ドメインを紐づけるまで

More than 3 years have passed since last update.

これまでさくら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を編集する
/etc/ssh/sshd_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を編集する
/etc/ssh/sshd_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をインストール
rbenvをインストール
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
rubyをインストール
rbenv install -v 2.1.3 # version2.1.3をインストール、バージョンは好みで変更
rbenv global 2.1.3
rbenv rehash
ruby -v # 上記のバージョンのrubyがインストールされていることを確認

RDSの設定

データベースを扱うRDSの設定を行っていきます。これも基本的にはぽちぽちやっていくだけです。これはドットインストールを参考にしました。

#10 データベースを立ち上げてみよう

注意する点としては、DB nameとMaster UsernameとMaster Passwordはrailsからアクセスする際にdatabase.ymlで設定する際に必要になるのでメモを取るなり覚えておきましょう。またエンドポイントというものがRDSの画面にありますが、ここで表示されているエンドポイントもアクセスする際に必要で、database.ymlに記述するのでメモしておきましょう。

RDSでの立ち上げが終了したらセキュリティグループの設定にて、mysqlの3306ポートを開くように設定しておきましょう。設定の際にはこちらを参考にしました。

0から始めるAWS入門④:RDS編

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になってしまう問題の対応方法

MySQL の文字コード設定を後から変えるには

ここまで設定したら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を参考にコピーして一部変更した感じです。下記のような形にしています。

nginxをインストール
sudo yum install nginx
sudo vi /etc/nginx/conf.d/[appname].conf # 下記のファイルの通りに編集
/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ログインが可能になります。

~/.ssh/config
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ファイルを下記のように修正します。

.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の追加の部分を読んでいただければと思います。

gitを使ったデプロイ方法

Unicornの設定

ここまでくればもう少しのはずですが、unicornの設定は若干はまりました。working_directoryの設定の際に、/currentの記述をしていなかったらCSSとjavascriptのファイルを読み込まずに3時間ぐらいはまっていました。。。

/var/www/[appname]/config/unicorn/production.rb
@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の再起動で反映されるかと思いきや反映されていなかったのでメモ。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away