船木俊介「ハッカーズランド」

スーパーソフトウエア東京オフィス代表&キッズラインCTO

UnicornとCapistrano3の設定 - Webサービス開発フロー(4)

前回からの続き

5.railsアプリケーションのデプロイ準備

Unicornでアプリケーション起動

ローカル開発環境のrailsアプリケーションに戻り、unicornを使えるようにします。

gem 'unicorn'
gem 'therubyracer',  platforms: :ruby
$ bundle install

config/unicorn.rbファイルを作成してUnicornを設定します。

config/unicorn.rb

rails_root = `pwd`.chomp

worker_processes 3
timeout 15
preload_app true

# TCPソケットで使う場合
listen 3000
# Unixドメインソケットを使う場合(WEBサーバーと連携する場合)
#listen "/tmp/unicorn.sock", :backlog => 64

pid "#{ rails_root }/tmp/pids/unicorn.pid"

# ログの設定方法.
stderr_path "#{ rails_root }/log/unicorn.log"
stdout_path "#{ rails_root }/log/unicorn.log"

before_fork do |server, worker|
  ActiveRecord::Base.connection.disconnect!
  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
        # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
    ActiveRecord::Base.establish_connection

    Signal.trap 'TERM' do
        puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
    end
end
$ bundle exec unicorn -D -c config/unicorn.rb

このコマンドでアプリケーションをUnicornで起動できます。http://localhost:3000/にアクセスして、WEBRick起動時と同様に表示されることを確認します。Unicornの停止は、psでプロセスIDを探して、そのプロセスをkillします。

$ ps aux | grep 'unicorn master'
$ kill -QUIT 99999

 

サーバでのnginxとの連携設定

サーバでは、nginxとUnicornを連携して動作させるため、TCPソケットからUnixドメインソケットへ設定を変更しておきます。

config/unicorn.rb

# TCPソケットで使う場合
#listen 3000
# Unixドメインソケットを使う場合(WEBサーバーと連携する場合)
listen "/tmp/unicorn.sock", :backlog => 64

 

Capistrano

デプロイは自動化ツールCapistrano3を使って行います。まずはGemfileに追加して、いつも通りbundle install。その後、deploy設定のファイルを編集していきます。設定ファイル中の(アプリケーション名)などは自分の環境に置き換えてください。

Gemfile

group :development do
  gem "capistrano"
  gem "capistrano-rails"
  gem "capistrano-bundler"
  gem "capistrano-rbenv"
  gem "capistrano3-unicorn"
end
$ bundle install

Capistranoの設定ファイルを生成します。

$ bundle exec cap install

mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

Capfile

require 'capistrano/setup'
require 'capistrano/deploy'

require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

config/deploy.rb

lock '3.3.5'

set :application, '(アプリケーション名 - rwerckersample)'
set :repo_url, '(GitHubのリポジトリURL - git@github.com:username/rweckersample.git)'

set :deploy_to, '/home/ec2-user/(rwerckersample)'
set :scm, :git
set :rbenv_ruby, '2.1.5'
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/assets public/uploads}
set :default_stage, "production"

set :default_env, {
  rbenv_root: "/home/ec2-user/rbenv",
  path: "/home/ec2-user/rbenv/shims:/home/ec2-user/rbenv/bin:$PATH",
  secret_key_base: '(予めrake secretコマンドで生成)'
}

set :unicorn_rack_env, "production"
set :unicorn_config_path, 'config/unicorn.rb'

namespace :deploy do

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

  after :publishing, :restart

  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
      # Here we can do anything such as:
      # within release_path do
      #   execute :rake, 'cache:clear'
      # end
    end
  end

end

config/deploy/production.rb

set :stage, :production
set :rails_env, :production

role :app, %w{ec2-user@(AWSサーバのIPアドレス)}
role :web, %w{ec2-user@(AWSサーバのIPアドレス)}
role :db,  %w{ec2-user@(AWSサーバのIPアドレス)}