序章

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

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

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

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

前提条件

このチュートリアルに従うには、次のものが必要です。

  • Ubuntu14.04×64ドロップレット
  • sudo権限を持つdeployという名前の非rootユーザー( Ubuntu 14.04 を使用した初期サーバーセットアップでは、これをセットアップする方法について説明しています)。
  • デプロイの準備ができているリモートgitリポジトリでホストされているWorkingRailsアプリ

オプションで、セキュリティを強化するために、SSH経由のrootログインを無効にし、 Ubuntu14.04を使用したサーバーの初期設定の説明に従ってSSHポート番号を変更できます。

警告: rootログインを無効にした後、deployユーザーとしてDropletにSSHで接続し、を閉じる前にこのユーザーにsudoを使用できることを確認してください。これらの変更を行うために開いたrootSSHセッション。

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

ステップ1—Nginxをインストールする

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

  1. sudo apt-get update

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

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

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

Railsアプリで使用するデータベースをインストールします。 選択できるデータベースはたくさんあるので、このガイドではそれらについては説明しません。 あなたはここで主要なもののための指示を見ることができます:

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

ステップ3—RVMとRubyをインストールする

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

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

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

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

  1. 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オプションは、stableを引数としてRVMインストールスクリプトに渡し、RVMの安定リリースをダウンロードしてインストールします。

注: 2番目のコマンドが「GPG署名の検証に失敗しました」というメッセージで失敗した場合、つまりGPGキーが変更された場合は、エラー出力からコマンドをコピーして実行し、署名をダウンロードします。 次に、RVMインストールのcurlコマンドを実行します。

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

  1. source ~/.rvm/scripts/rvm
  2. rvm requirements

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

  1. rvm install 2.2.1
  2. rvm use 2.2.1 --default

ステップ4—RailsとBundlerをインストールする

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

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

  1. gem install rails -V --no-ri --no-rdoc
  2. gem install bundler -V --no-ri --no-rdoc

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

  • -V(詳細出力):Gemのインストールに関する詳細情報を出力します
  • --no-ri-(Riドキュメントをスキップ):Riドキュメントをインストールしないため、スペースが節約され、インストールが高速になります
  • --no-rdoc-(RDocsをスキップ):RDocsをインストールしないため、スペースが節約され、インストールが高速化されます

注: -vフラグを使用して、要件に応じて特定のバージョンのRailsをインストールすることもできます。

  1. gem install rails -v '4.2.0' -V --no-ri --no-rdoc

ステップ5—SSHキーを設定する

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

  1. ssh -T [email protected]
  2. ssh -T [email protected]

Permission denied (publickey)メッセージが表示されても心配しないでください。 次に、サーバーのSSHキー(公開鍵と秘密鍵のペア)を生成します。

  1. ssh-keygen -t rsa

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

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

  1. git clone [email protected]:username/appname.git

テスト用のサンプルアプリが必要な場合は、このチュートリアル用に特別に作成された次のテストアプリをフォークできます。GitHub上のサンプルRailsアプリ

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

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

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

  1. ssh-keygen -t rsa

ドロップレットの承認済みキーファイルにローカルSSHキーを追加します(ポート番号をカスタマイズしたポート番号に置き換えることを忘れないでください)。

  1. cat ~/.ssh/id_rsa.pub | ssh -p your_port_num deploy@your_server_ip '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'

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

  1. bundle

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

  1. cap install

これにより、次のものが作成されます。

  • RailsアプリのルートディレクトリにあるCapfile
  • configディレクトリのdeploy.rbファイル
  • configディレクトリ内のdeployディレクトリ

Capfileの内容を次のように置き換えます。

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の内容を次のように置き換え、アプリとドロップレットパラメーターで赤でマークされたフィールドを更新します。

config / deploy.rb

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

set :repo_url,        '[email protected]:username/appname.git'
set :application,     'appname'
set :user,            'deploy'
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/deploy/apps/appname/shared/tmp/sockets/appname-puma.sock;
}

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

  root /home/deploy/apps/appname/current/public;
  access_log /home/deploy/apps/appname/current/log/nginx.access.log;
  error_log /home/deploy/apps/appname/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アプリを使用している場合は、行った変更をコミットし、ローカルマシンからリモートにプッシュします。

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

注:このシステムからGitHubを初めて使用する場合は、GitHubのユーザー名とメールアドレスを使用して次のコマンドを発行する必要がある場合があります。

  1. git config --global user.name 'Your Name'
  2. git config --global user.email [email protected]

ここでも、ローカルマシンから、最初の展開を行います。

  1. cap production deploy:initial

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

すべてが順調に進んだら、PumaWebサーバーをNginxリバースプロキシに接続する準備が整いました。

ドロップレットで、nginx.confsites-enabledディレクトリにシンボリックリンクします。

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

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

  1. sudo service nginx restart

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

通常の展開

アプリに変更を加えてサーバーに新しいリリースをデプロイする場合は、変更をコミットし、通常どおりgitリモートにプッシュして、deployコマンドを実行します。

  1. git add -A
  2. git commit -m "Deploy Message"
  3. git push origin master
  4. cap production deploy

注: config/nginx.confファイルに変更を加えた場合は、アプリをデプロイした後、サーバーでNginxサービスをリロードまたは再起動する必要があります。

  1. sudo service nginx restart

結論

さて、これで、WebサーバーとしてPumaを使用し、基本設定で構成されたNginxとCapistranoを使用してDropletでRailsアプリを実行することになります。 ここで、Railsアプリケーションを最大限に活用するために構成を最適化するのに役立つ他のドキュメントを確認する必要があります。