LoginSignup
213
194

More than 5 years have passed since last update.

Capistrano3でUnicorn+Nginxな環境にRailsをデプロイする:初心者向け

Last updated at Posted at 2014-09-21

この手の記事は、もう散々出尽くしている感が満載ですが、そんな記事を見ても1発で完了できず、微妙に考え方の違う複数ある記事をつまみ食いして死亡という、スキル不足な初心者にありがちなパターンを王道でいってしまったので、初心者が初心者に送る一つの道標になればと。

前提

  • Capistrano v3.2.1
  • Rails v4.1
  • rbenv v0.4.0
  • Ruby v2.1.2
  • Unicorn v4.8.3
  • Nginx v1.4.7
  • Git
  • GitHub

こんな感じで動作確認済み。

Webサーバ(nginx)とAppサーバ(unicorn)は同一のステージングサーバにデプロイするのを想定した構築メモです。GitでRailsアプリをバージョン管理し、ローカルからステージングサーバへCapistranoでGitリポジトリ経由でデプロイします。

設定

GitHub

GitHubからデプロイするためにDeploy keysを設定する必要があります。対象リポジトリページの「Settings」→「Deploy keys」に移動し、デプロイ対象サーバの公開鍵を登録します。

Gemライブラリ

デプロイに必要な部分のみ記載しておきます。適宜、アプリケーションに必要なものを追記してください。

Gemfile
gem 'dotenv-rails' #環境変数を簡単に扱うのに使用

group :development, :test do
  gem 'capistrano', '~> 3.2.1'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano3-unicorn' #Unicornの起動を簡単に行える
end

group :production, :staging do
  gem 'unicorn'
end
$ bundle install

人によっては、dotenv-railscapistrano3-unicornは使わず、自前で行うかもしれないですが、これを使ったほうが楽だったので。

デプロイ設定

Capistranoは初期設定コマンドがあるので、それを使ってもいいんだけど、使わなくてもいいです。単に初期テンプレートファイルを作ってくれるだけなので。

$ bundle exec cap install
/Capfile
require 'capistrano/setup'
require 'capistrano/deploy'

# rbenvを使用している場合
require 'capistrano/rbenv'

# デプロイ先のサーバで、ユーザディレクトリでrbenvをインストールしている場合
set :rbenv_type, :user
set :rbenv_ruby, '2.1.2'

require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

require 'capistrano3/unicorn'

# Rails4から分離したsecrets.ymlの環境変数を .envファイルで管理する
set :linked_files, %w{config/secrets.yml .env}

# タスクを読み込むけど、今回は特に使わない
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
/config/deploy.rb
lock '3.2.1'

set :application, 'myapp'
set :repo_url, 'GitのリポジトリURL'
set :branch, 'master'
set :deploy_to, '/var/www/myapp'
set :scm, :git
set :log_level, :debug
set :pty, true
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets bundle public/system public/assets}
set :default_env, { path: "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH" }
set :keep_releases, 5

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do

  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart'
  end
end

前述したsecret_key_baseを環境変数で設定するため、stagingの項目を追加するのみでOK。

/config/secrets.yml
development:
  secret_key_base: bbbb # 適当

test:
  secret_key_base: aaaa # 適当

staging:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

Railsアプリの稼働ディレクトリを仮に/var/www/myappと設定。

/config/unicorn/staging.rb
@app_path = '/var/www/myapp'
working_directory @app_path + "/current"

worker_processes 2
preload_app true
timeout 30
listen "/tmp/unicorn.sock", :backlog => 64
pid "/var/www/myapp/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

/config/environments/staging.rbは、特に指定がなければproduction.rbをそのままコピー。

/config/environments/staging.rb
Rails.application.configure do
  config.cache_classes = true
  config.eager_load = true
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
  config.serve_static_assets = false
  config.assets.js_compressor = :uglifier
  config.assets.compile = false
  config.assets.digest = true
  config.log_level = :info
  config.i18n.fallbacks = true
  config.active_support.deprecation = :notify
  config.log_formatter = ::Logger::Formatter.new
  config.active_record.dump_schema_after_migration = false
end

デプロイ先のサーバ名とSSHのログインIDを指定。デプロイ元から、秘密鍵でデプロイ先サーバにアクセス可能なのが前提条件です。ssh_optionsで鍵などの細かい指定は可能ですが、そのままでいけるなら、設定不要。

/config/deploy/staging.rb
set :rails_env, "staging"
set :unicorn_rack_env, "staging"

role :app, %w{user@example.com}
role :web, %w{user@example.com}
role :db,  %w{user@example.com}

server 'example.com', user: 'user', roles: %w{web app}

set :ssh_options, {
  keys: %w(/home/vagrant/.ssh/id_rsa),
  forward_agent: false,
  auth_methods: %w(publickey)
}

ステージングサーバの環境構築

ステージングサーバ自体がRailsが稼働できるようにしておく必要があります。今どきならChefとかを使ってローカルでもステージングサーバでも同一の環境になっていたりすると思いますが。

環境変数の設定

ただ一つだけ、環境変数の管理を直接サーバで行っておきます。

/var/www/myapp/shared/.env
SECRET_KEY_BASE="hogehoge"
/var/www/myapp/shared/config/secrets.yml
staging:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

dotenvというGemライブラリを使っているのだけど、これで使い方が正しいのかはちょっと微妙…。

nginxの設定

nginxは単純にUnicornの前に立ってるだけなのでシンプル。

/etc/nginx/conf.d/hoge.conf
upstream unicorn_server {
    server unix:/tmp/unicorn.sock
    fail_timeout=0;
}

server {
    listen 80;
    client_max_body_size 4G;
    server_name _;

    keepalive_timeout 5;

    # Location of our static files
    root /var/www/myapp/public;

    location ~ ^/assets/ {
        root /var/www/myapp/shared/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/myapp/public;
    }
}

デプロイ実行

デプロイ自体は非常に簡単なコマンドです。

$ bundle exec cap staging deploy

実行前に、簡単なチェックも可能。

$ bundle exec cap staging deploy:check

これで、上手く行けばデプロイ先のステージングサーバにUnicornのプロセスが起動しているはずです。psコマンドで確認してみてください。

Unicornの停止と再起動とか

起動

$ bundle exec unicorn -c /var/www/myapp/current/config/unicorn/staging.rb -E deployment -D

停止

$ kill -QUIT `cat /var/www/myapp/shared/tmp/pids/unicorn.pid`

再起動

$ kill -HUP `cat /var/www/myapp/shared/tmp/pids/unicorn.pid`
213
194
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
213
194