Capistrano、Nginx、Pumaを使用してUbuntu 14.04にRailsアプリをデプロイする

前書き

Railsは、Rubyで書かれたオープンソースのWebアプリケーションフレームワークです。 それは、「構成よりも規約」の哲学に従い、物事を行うための「最良の」方法があると仮定します。 これにより、無限の構成ファイルを経由することなく、より多くのことを達成しながら、より少ないコードを書くことができます。

Nginxは、高性能HTTPサーバー、リバースプロキシ、および同時実行性、安定性、スケーラビリティ、低メモリ消費に重点を置いていることで知られるロードバランサーです。 Nginxと同様に、Pumaはメモリフットプリントが非常に小さい別の非常に高速で同時実行可能なWebサーバーですが、Ruby Webアプリケーション用に構築されています。

Capistranoは、主にRuby Webアプリに焦点を当てたリモートサーバー自動化ツールです。 SSHを介して任意のワークフローをスクリプト化し、アセットのプリコンパイルやRailsサーバーの再起動などの一般的なタスクを自動化することにより、任意の数のリモートマシンにWebアプリを確実にデプロイするために使用されます

このチュートリアルでは、DigitalOcean Ubuntu DropletにRubyとNginxをインストールし、WebアプリでPumaとCapistranoを構成します。 Nginxは、クライアント要求をキャプチャし、それらをRailsを実行しているPuma Webサーバーに渡すために使用されます。 Capistranoを使用して一般的な展開タスクを自動化するため、Railsアプリの新しいバージョンをサーバーに展開するたびに、いくつかの簡単なコマンドでそれを行うことができます。

前提条件

このチュートリアルを実行するには、次のものが必要です。

  • Ubuntu 14.04 x64ドロップレット

  • sudo権限を持つ「+ deploy +」という名前の非ルートユーザー(https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04[Ubuntu 14.04での初期サーバーセットアップ]の説明これを設定する方法。)

  • デプロイする準備ができているリモートgitリポジトリでホストされている作業用Railsアプリ

オプションで、セキュリティを強化するために、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04で説明されているように、SSH経由でルートログインを無効にし、SSHポート番号を変更できます[ Ubuntu 14.04での初期サーバーセットアップ]。

このチュートリアルのすべてのコマンドは、 `+ deploy `ユーザーとして実行する必要があります。 コマンドにルートアクセスが必要な場合は、先頭に「 sudo +」が付きます。

ステップ1-Nginxのインストール

VPSが安全になったら、パッケージのインストールを開始できます。 パッケージインデックスファイルを更新します。

sudo apt-get update

次に、Nginxをインストールします。

sudo apt-get install curl git-core nginx -y

ステップ2-データベースのインストール

Railsアプリで使用するデータベースをインストールします。 選択できるデータベースは多数あるため、このガイドではそれらを取り上げません。 ここで主要なものの手順を見ることができます:

また、必ずチェックアウトしてください:

ステップ3-RVMとRubyのインストール

Rubyを直接インストールすることはありません。 代わりに、Rubyバージョンマネージャーを使用します。 多くの選択肢(rbenv、chrubyなど)がありますが、このチュートリアルではRVMを使用します。 RVMを使用すると、同じシステムに複数のルビーを簡単にインストールして管理し、アプリに応じて正しいルビーを使用できます。 これにより、新しいrubyを使用するためにRailsアプリをアップグレードする必要がある場合に、作業がはるかに簡単になります。

RVMをインストールする前に、RVM GPGキーをインポートする必要があります。

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

次に、RVMをインストールしてルビーを管理します。

curl -sSL https://get.rvm.io | bash -s stable

このコマンドは、「+ curl」を使用して「+ https://get.rvm.io」からRVMインストールスクリプトをダウンロードします。 `+ -sSL +`オプションは3つのフラグで構成されています:

  • 「+ -s +」はcurlに「サイレントモード」でファイルをダウンロードするよう指示します

  • `+ -S +`は、失敗した場合にエラーメッセージを表示するようcurlに指示します

  • `+ -L +`は、インストールスクリプトの取得中にすべてのHTTPリダイレクトに従うようにcurlに指示します

ダウンロードされると、スクリプトは「+ bash」にパイプされます。 `+ -s `オプションは、RVMインストールスクリプトの引数として ` stable +`を渡し、RVMの安定リリースをダウンロードしてインストールします。

RVMスクリプトを(関数として)ロードして、使用を開始できるようにする必要があります。 次に、 `+ requirements +`コマンドを実行して、RVMとRubyが適切に機能するために必要な依存関係とファイルを自動的にインストールする必要があります。

source ~/.rvm/scripts/rvm
rvm requirements

これで、選択したRubyをインストールできます。 最新の + Ruby 2.2.1 +(執筆時点)をデフォルトのRubyとしてインストールします。

rvm install 2.2.1
rvm use 2.2.1 --default

ステップ4-RailsとBundlerのインストール

Rubyをセットアップしたら、Rubygemsのインストールを開始できます。 まず、Railsアプリケーションを実行できるRails gemをインストールします。次に、アプリの `+ Gemfile `を読み取り、必要なすべてのgemを自動的にインストールできる ` bundler +`をインストールします。

Rails and Bundlerをインストールするには:

gem install rails -V --no-ri --no-rdoc
gem install bundler -V --no-ri --no-rdoc

3つのフラグが使用されました。

  • + -V +(詳細出力):Gemインストールに関する詳細情報を出力します

  • +-no-ri +-(Riドキュメントをスキップ):Ri Docsをインストールせず、スペースを節約し、インストールを高速化します

  • +-no-rdoc +-(RDocsをスキップ):RDocsをインストールせず、スペースを節約してインストールを高速化します

ステップ5-SSHキーのセットアップ

スムーズな展開を設定するため、認証にSSHキーを使用します。 まず、GitHub、Bitbucket、またはRailsアプリのコードベースがホストされている他のGit Remoteと握手します。

「+ Permission denied(publickey)+」メッセージが表示されても心配する必要はありません。 次に、サーバーのSSHキー(公開/秘密キーペア)を生成します。

ssh-keygen -t rsa

新しく作成した公開キー( +〜/ .ssh / id_rsa.pub +)をリポジトリの展開キーに追加します。

すべての手順が正しく完了したら、パスワードを入力せずにgitリポジトリ(HTTPではなくSSHプロトコル経由)を「+ clone +」できるようになります。

git clone

テスト用のサンプルアプリが必要な場合は、このチュートリアル専用に作成された次のテストアプリをフォークできます。https://github.com/sheharyarn/testapp_rails[GitHubのサンプルRailsアプリ]

`+ git clone `コマンドは、アプリと同じ名前のディレクトリを作成します。 たとえば、 ` testapp_rails +`という名前のディレクトリが作成されます。

デプロイメントキーが機能しているかどうかを確認するためだけにクローンを作成しています。新しい変更をプッシュするたびにリポジトリをクローンまたはプルする必要はありません。 Capistranoがすべてを処理します。 必要に応じて、このクローンディレクトリを削除できます。

ローカルマシンでターミナルを開きます。 ローカルコンピューター用のSSHキーがない場合は、それも作成します。 ローカルターミナルセッションで:

ssh-keygen -t rsa

ローカルのSSHキーをDropletの_Authorized Keys_ファイルに追加します(ポート番号をカスタマイズしたポート番号に置き換えてください):

cat ~/.ssh/id_rsa.pub | ssh -p  deploy@ 'cat >> ~/.ssh/authorized_keys'

ステップ6-Railsアプリでデプロイメント構成を追加する

ローカルマシンで、RailsアプリケーションでNginxとCapistranoの構成ファイルを作成します。 Railsアプリの `+ Gemfile +`に次の行を追加することから始めます。

Gemfile

group :development do
   gem 'capistrano',         require: false
   gem 'capistrano-rvm',     require: false
   gem 'capistrano-rails',   require: false
   gem 'capistrano-bundler', require: false
   gem 'capistrano3-puma',   require: false
end

gem 'puma'

`+ Gemfile `で指定したgemをインストールするには、 ` bundler +`を使用します。 次のコマンドを入力して、Railsアプリをバンドルします。

bundle

バンドルした後、次のコマンドを実行してCapistranoを構成します。

cap install

これにより、以下が作成されます。

  • Railsアプリのルートディレクトリにある「+ Capfile +」

  • `+ config `ディレクトリの ` deploy.rb +`ファイル

  • + config`ディレクトリ内の + deploy`ディレクトリ

`+ Capfile +`の内容を次のものに置き換えます:

キャップファイル

# Load DSL and Setup Up Stages
require 'capistrano/setup'
require 'capistrano/deploy'

require 'capistrano/rails'
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/puma'

# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

この `+ Capfile +`は、事前に定義されたタスクをCapistrano構成ファイルにロードして、デプロイメントを自動化するなどの手間をかけないようにします。

  • 正しいRubyを選択する

  • アセットのプリコンパイル

  • Gitリポジトリーを正しい場所に複製する

  • Gemfileが変更されたときに新しい依存関係をインストールする

`+ config / deploy.rb +`の内容を次のものに置き換え、アプリとDropletのパラメーターで赤でマークされたフィールドを更新します:

config / deploy.rb

# Change these
server , port: , roles: [:web, :app, :db], primary: true

set :repo_url,
set :application,
set :user,
set :puma_threads,    [4, 16]
set :puma_workers,    0

# Don't change these unless you know what you're doing
set :pty,             true
set :use_sudo,        false
set :stage,           :production
set :deploy_via,      :remote_cache
set :deploy_to,       "/home/#{fetch(:user)}/apps/#{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, "#{release_path}/log/puma.error.log"
set :puma_error_log,  "#{release_path}/log/puma.access.log"
set :ssh_options,     { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true  # Change to false when not using ActiveRecord

## Defaults:
# set :scm,           :git
# set :branch,        :master
# set :format,        :pretty
# set :log_level,     :debug
# set :keep_releases, 5

## Linked Files & Directories (Default None):
# set :linked_files, %w{config/database.yml}
# set :linked_dirs,  %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}

namespace :puma do
 desc 'Create Directories for Puma Pids and Socket'
 task :make_dirs do
   on roles(:app) do
     execute "mkdir #{shared_path}/tmp/sockets -p"
     execute "mkdir #{shared_path}/tmp/pids -p"
   end
 end

 before :start, :make_dirs
end

namespace :deploy do
 desc "Make sure local git is in sync with remote."
 task :check_revision do
   on roles(:app) do
     unless `git rev-parse HEAD` == `git rev-parse origin/master`
       puts "WARNING: HEAD is not the same as origin/master"
       puts "Run `git push` to sync changes."
       exit
     end
   end
 end

 desc 'Initial Deploy'
 task :initial do
   on roles(:app) do
     before 'deploy:restart', 'puma:start'
     invoke 'deploy'
   end
 end

 desc 'Restart application'
 task :restart do
   on roles(:app), in: :sequence, wait: 5 do
     invoke 'puma:restart'
   end
 end

 before :starting,     :check_revision
 after  :finishing,    :compile_assets
 after  :finishing,    :cleanup
 after  :finishing,    :restart
end

# ps aux | grep puma    # Get puma pid
# kill -s SIGUSR2 pid   # Restart puma
# kill -s SIGTERM pid   # Stop puma

この `+ deploy.rb +`ファイルには、アプリのリリースを管理し、デプロイ時にいくつかのタスクを自動的に実行するのに役立つ、すぐに使用できるいくつかの適切なデフォルトが含まれています。

  • Railsアプリのデフォルト環境として「+ production +」を使用します

  • アプリの複数のリリースを自動的に管理します

  • 最適化されたSSHオプションを使用

  • Gitのリモートが最新かどうかを確認します

  • アプリのログを管理します

  • Pumaワーカーの管理時にアプリをメモリにプリロードします

  • 展開の完了後にPumaサーバーを起動(または再起動)します

  • リリースの特定の場所にあるPumaサーバーへのソケットを開きます

要件に応じて、すべてのオプションを変更できます。 次に、Nginxを構成する必要があります。 Railsプロジェクトディレクトリに `+ config / nginx.conf +`を作成し、次のコードを追加します(これもパラメーターに置き換えます)。

config / nginx.conf

upstream puma {
 server unix:///home//apps//shared/tmp/sockets/-puma.sock;
}

server {
 listen 80 default_server deferred;
 # server_name example.com;

 root /home//apps//current/public;
 access_log /home//apps//current/log/nginx.access.log;
 error_log /home//apps//current/log/nginx.error.log info;

 location ^~ /assets/ {
   gzip_static on;
   expires max;
   add_header Cache-Control public;
 }

 try_files $uri/index.html $uri @puma;
 location @puma {
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header Host $http_host;
   proxy_redirect off;

   proxy_pass http://puma;
 }

 error_page 500 502 503 504 /500.html;
 client_max_body_size 10M;
 keepalive_timeout 10;
}

前のファイルと同様に、この `+ nginx.conf `には、 ` deploy.rb `ファイルの設定ですぐに使用できるデフォルトが含まれています。 これは、ポート80でトラフィックをリッスンし、リクエストをPumaソケットに渡し、nginxログをアプリの「現在の」リリースに書き込み、すべてのアセットを圧縮して最大有効期限でブラウザーにキャッシュし、HTMLページを公開しますフォルダーを静的ファイルとして設定し、デフォルトの最大の「 Client Body Size 」と「 Request Timeout +」の値を設定します。

ステップ7-Railsアプリケーションのデプロイ

独自のRailsアプリを使用している場合は、行った変更をコミットし、ローカルマシンからリモートにプッシュします。

git add -A
git commit -m "Set up Puma, Nginx & Capistrano"
git push origin master

繰り返しますが、ローカルマシンから最初の展開を行います。

cap production deploy:initial

これにより、RailsアプリがDropletにプッシュされ、アプリに必要なすべてのgemがインストールされ、Puma Webサーバーが起動します。 これには、アプリで使用するGemの数に応じて、5〜15分かかります。 このプロセスが発生すると、デバッグメッセージが表示されます。

すべてが順調に進むと、Puma WebサーバーをNginxリバースプロキシに接続する準備が整いました。

ドロップレットで、 + nginx.conf`を + sites-enabled`ディレクトリにシンボリックリンクします:

sudo rm /etc/nginx/sites-enabled/default
sudo ln -nfs "/home//apps//current/config/nginx.conf" "/etc/nginx/sites-enabled/"

Nginxサービスを再起動します。

sudo service nginx restart

WebブラウザでサーバーIPを指定し、Railsアプリの動作を確認できるようになりました。

通常の展開

アプリに変更を加え、新しいリリースをサーバーにデプロイしたいときはいつでも、変更をコミットし、通常のようにgitリモートにプッシュして、 `+ deploy +`コマンドを実行します:

git add -A
git commit -m "Deploy Message"
git push origin master
cap production deploy

結論

OK 次に、Railsアプリケーションを最大限に活用するための構成の最適化に役立つ他のドキュメントをご覧ください。

Related