Ubuntu+Nginx+Unicorn+Rails+Capistrano+Resque+God — Gist
この記事から設定を例として抽出
定義更新する
- God はシステム(のrbenv)とかで入れてる前提なので、そうじゃない場合は適宜変更する。
Ubuntu+Nginx+Unicorn+Rails+Capistrano+Resque+God — Gist
この記事から設定を例として抽出
定義更新する
# This file is used by Rack-based servers to start the application. | |
require ::File.expand_path('../config/environment', __FILE__) | |
require 'unicorn/oob_gc' | |
use Unicorn::OobGC, 5 | |
run AppName::Application |
# -*- coding: utf-8 -*- | |
# deploy 時に自動で bundle install | |
require 'bundler/capistrano' | |
# deploy 時に自動で rake assets:precompile | |
load 'deploy/assets' | |
default_run_options[:pty] = true | |
# アプリケーションの設定 | |
set :application, 'app' # Change! | |
set :domain, 'app.com' # Change! | |
set :rails_env, 'production' | |
set :user, 'deployer' # Change! | |
set :runner, 'deployer' # Change! | |
set :repository, "[email protected]" # Change! | |
set :scm, :git | |
set :bundle_gemfile, "Gemfile" | |
set :bundle_flags, "--quiet" | |
set :deploy_via, :copy | |
set :deploy_to, "/home/#{user}/#{application}" | |
set :use_sudo, false | |
server domain, :app, :web | |
set :god_dir, '/etc/god' | |
set(:god_cmd) { "#{sudo} /usr/local/rbenv/shims/god" } | |
set(:local_unicorn_god_name) { "unicorn-#{rails_env}.god" } | |
set(:local_resque_god_name) { "resque-#{rails_env}.god" } | |
set(:local_resque_scheduler_god_name) {"resque-scheduler-#{rails_env}.god" } | |
set(:unicorn_god_name) { "#{application}-unicorn-#{rails_env}.god" } | |
set(:resque_god_name) { "#{application}-resque-#{rails_env}.god" } | |
set(:resque_scheduler_god_name) { "#{application}-resque-scheduler-#{rails_env}.god" } | |
# 再起動後に古い releases を cleanup | |
after "deploy:restart", 'deploy:cleanup', "unicorn:update_config", "resque:update_config", "god:reload_resque", "god:reload_unicorn" | |
after "deploy:setup", "db:create", "unicorn:setup", "resque:setup" | |
after "deploy", "deploy:migrate" | |
namespace :unicorn do | |
task :setup do | |
upload("config/#{local_unicorn_god_name}", "/tmp/#{unicorn_god_name}") | |
run "#{sudo} mv /tmp/#{unicorn_god_name} /etc/god/#{unicorn_god_name}" | |
end | |
task :update_config do | |
run "cd #{current_path} && #{sudo} cp config/#{local_unicorn_god_name} #{File.join(god_dir, unicorn_god_name)}" | |
end | |
end | |
namespace :resque do | |
task :setup do | |
upload("config/#{local_resque_god_name}", "/tmp/#{resque_god_name}") | |
run "#{sudo} mv /tmp/#{resque_god_name} /etc/god/#{resque_god_name}" | |
upload("config/#{local_resque_scheduler_god_name}", "/tmp/#{resque_scheduler_god_name}") | |
run "#{sudo} mv /tmp/#{resque_scheduler_god_name} /etc/god/#{resque_scheduler_god_name}" | |
end | |
task :update_config do | |
run "cd #{current_path} && #{sudo} cp config/#{local_resque_god_name} #{File.join(god_dir, resque_god_name)}" | |
run "cd #{current_path} && #{sudo} cp config/#{local_resque_scheduler_god_name} #{File.join(god_dir, resque_scheduler_god_name)}" | |
end | |
end | |
namespace :god do | |
desc "Hot-reload God configuration for the Resque worker" | |
task :restart_resque do | |
run "#{god} stop resque" | |
run "#{god} load #{File.join(god_dir, resque_god_name)}" | |
run "#{god} start resque" | |
run "#{god} stop resque-scheduler" | |
run "#{god} load #{File.join(god_dir, resque_scheduler_god_name)}" | |
run "#{god} start resque-scheduler" | |
end | |
task :reload_resque do | |
run "#{god} restart resque" | |
run "#{god} restart resque-scheduler" | |
end | |
desc "Hot-reload God configuration for the Unicorn" | |
task :reload_unicorn do | |
run "#{god} restart unicorn" | |
end | |
desc "Restart God configuration for the Unicorn" | |
task :restart_unicorn do | |
run "#{god} stop unicorn" | |
run "#{god} load #{File.join(god_dir, unicorn_god_name)}" | |
run "#{god} start unicorn" | |
end | |
end |
# capistrano-nginxでデプロイするのでERB | |
upstream <%= application %> { | |
server unix:/tmp/<%= application %>-unicorn.sock fail_timeout=30s max_fails=3; | |
} | |
server { | |
listen 80; | |
server_name app.com; # Change! | |
root /home/<%= user %>/<%= application %>/current/public; | |
access_log /var/log/nginx/<%= application %>.access.log; | |
error_log /var/log/nginx/<%= application %>.error.log; | |
location / { | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_pass http://unicorn.app.com; | |
} | |
location = /favicon.ico { | |
gzip_static on; | |
# http://wiki.nginx.org/HttpGzipModule#gzip_vary | |
gzip_vary on; | |
expires max; | |
add_header Cache-Control public; | |
} | |
location = /robots.txt { | |
} | |
location ~ ^/(assets|images|javascripts|stylesheets|system)/ { | |
gzip_static on; | |
# http://wiki.nginx.org/HttpGzipModule#gzip_vary | |
gzip_vary on; | |
expires max; | |
add_header Cache-Control public; | |
} | |
} |
# In config/resque-production.god | |
God.watch do |w| | |
w.name = 'resque' | |
w.interval = 30.seconds | |
w.env = { 'RAILS_ENV' => 'production', 'QUEUE' => '*' } | |
w.uid = 'DEPLOYER' # Change! | |
w.gid = 'GROUP' # Change! | |
w.dir = '/home/DEPLOYER/APPNEME/current' # Change! | |
w.start = "bundle exec rake resque:work" | |
w.start_grace = 10.seconds | |
w.log = '/home/DEPLOYER/APPNAME/current/log/resque-worker.log' # Change! | |
# restart if memory gets too high | |
w.transition(:up, :restart) do |on| | |
on.condition(:memory_usage) do |c| | |
c.above = 100.megabytes | |
c.times = 2 | |
end | |
end | |
# determine the state on startup | |
w.transition(:init, { true => :up, false => :start }) do |on| | |
on.condition(:process_running) do |c| | |
c.running = true | |
end | |
end | |
# determine when process has finished starting | |
w.transition([:start, :restart], :up) do |on| | |
on.condition(:process_running) do |c| | |
c.running = true | |
c.interval = 5.seconds | |
end | |
# failsafe | |
on.condition(:tries) do |c| | |
c.times = 5 | |
c.transition = :start | |
c.interval = 5.seconds | |
end | |
end | |
# start if process is not running | |
w.transition(:up, :start) do |on| | |
on.condition(:process_running) do |c| | |
c.running = false | |
end | |
end | |
end | |
# vim: set filetype=ruby: |
# In config/resque-scheduler-production.god | |
God.watch do |w| | |
w.name = 'resque-scheduler' | |
w.interval = 30.seconds | |
w.env = { 'RAILS_ENV' => 'production', 'QUEUE' => '*' } | |
w.uid = 'DEPLOYER' # Change! | |
w.gid = 'GROUP' # Change! | |
w.dir = '/home/DEPLOYER/APPNEME/current' # Change! | |
w.start = "bundle exec rake resque:scheduler" | |
w.start_grace = 10.seconds | |
w.log = '/home/DEPLOYER/APPNAME/current/log/resque-scheduler-worker.log' # Change | |
# restart if memory gets too high | |
w.transition(:up, :restart) do |on| | |
on.condition(:memory_usage) do |c| | |
c.above = 100.megabytes | |
c.times = 2 | |
end | |
end | |
# determine the state on startup | |
w.transition(:init, { true => :up, false => :start }) do |on| | |
on.condition(:process_running) do |c| | |
c.running = true | |
end | |
end | |
# determine when process has finished starting | |
w.transition([:start, :restart], :up) do |on| | |
on.condition(:process_running) do |c| | |
c.running = true | |
c.interval = 5.seconds | |
end | |
# failsafe | |
on.condition(:tries) do |c| | |
c.times = 5 | |
c.transition = :start | |
c.interval = 5.seconds | |
end | |
end | |
# start if process is not running | |
w.transition(:up, :start) do |on| | |
on.condition(:process_running) do |c| | |
c.running = false | |
end | |
end | |
end | |
# vim: set filetype=ruby: |
# In unicorn.conf | |
# -*- coding: utf-8 -*- | |
listen "/tmp/APPNAME-unicorn.sock" # Change! | |
worker_processes 3 | |
pid "tmp/pids/unicorn.pid" | |
stderr_path "log/unicorn.stderr.log" | |
stdout_path "log/unicorn.stdout.log" | |
preload_app true | |
before_fork do |server, worker| | |
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! | |
old_pid = "#{server.config[:pid]}.oldbin" | |
if File.exists?(old_pid) && server.pid != old_pid | |
begin | |
Process.kill("WINCH", File.read(old_pid).to_i) | |
Thread.new { | |
sleep 30 | |
Process.kill("KILL", 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| | |
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection | |
end | |
# vim:set ft=ruby: |