Danny
Danny

Reputation: 4124

Capistrano-unicorn gem getting wrong environment set

I've been using this gem for a while and just took the dive to try deploying an actual staging environment to my staging server, and I ran into issues. Unicorn starts with the command unicorn_rails and -E production despite all the settings being correct afaik.

I noticed in deploy.rb that my unicorn_bin variable was set as unicorn_rails. I took out this setting in my deploy.rb. However unicorn:duplicate still executes the unicorn_rails command, when the default should be unicorn.

My vars are all set to staging in the deploy/staging.rb, as outlined in the multistage setup wiki document, but I noticed -E is still getting set to production.

Relevent info:

Here's my output from my unicorn.log file after a deploy:

executing ["/var/www/apps/myapp/shared/bundle/ruby/2.0.0/bin/unicorn_rails", "-c", "/var/www/apps/bundio/current/config/unicorn.rb", "-E", "production", "-D", {12=>#<Kgio::UNIXServer:/tmp/bundio.socket>, 13=>#<Kgio::TCPServer:fd 13>}] (in /var/www/apps/bundio/current)

Here's the output from cap -T (defaults to staging)

# Environments
rails_env          "staging"
unicorn_env        "staging"
unicorn_rack_env   "staging"

# Execution
unicorn_user       nil
unicorn_bundle     "/usr/local/rvm/gems/ruby-2.0.0-p247@global/bin/bundle"
unicorn_bin        "unicorn"
unicorn_options    ""
unicorn_restart_sleep_time  2

# Relative paths
app_subdir                         ""
unicorn_config_rel_path            "config"
unicorn_config_filename            "unicorn.rb"
unicorn_config_rel_file_path       "config/unicorn.rb"
unicorn_config_stage_rel_file_path "config/unicorn/staging.rb"

# Absolute paths
app_path                  "/var/www/apps/myapp/current"
unicorn_pid               "/var/www/apps/myapp/shared/pids/unicorn.myapp.pid"
bundle_gemfile            "/var/www/apps/myapp/current/Gemfile"
unicorn_config_path       "/var/www/apps/myapp/current/config"
unicorn_config_file_path  "/var/www/apps/myapp/current/config/unicorn.rb"
unicorn_config_stage_file_path
->                        "/var/www/apps/myapp/current/config/unicorn/staging.rb"

And another curiousity, the unicorn_rails -E flag should reference the rails environment, whereas the unicorn -E should reference the rack env -- the rack env should only get the values developement and deployment, but it gets set to production, which is a bit strange (see unicorn docs for settings of the RACK_ENV variable.

Any insight into this would be much appreciated. On my staging server, I've also set the RAILS_ENV to staging. I've set up the things for rails for another environment, like adding staging.rb in my environments folder, adding a staging section to database.yml, etc.

Important lines in lib/capistrano-unicorn/config.rb talking about unicorn_rack_env:

_cset(:unicorn_env)                { fetch(:rails_env, 'production' ) }
_cset(:unicorn_rack_env) do
# Following recommendations from http://unicorn.bogomips.org/unicorn_1.html
fetch(:rails_env) == 'development' ? 'development' : 'deployment'
end

Thanks in advance.

Upvotes: 1

Views: 1240

Answers (1)

Danny
Danny

Reputation: 4124

Ok, after a long time not having the correct environment, I have discovered the issue!

Basically, my init scripts were running BEFORE my capistrano-unicorn bin was doing its thing.

So, make sure that your init.d or upstart scripts to manage Unicorn and its workers are taken into account when capistrano-unicorn is doing the unicorn restart / reload / duplication tasks.

I did not think to look at these scripts when I had to debug the stale pid file / already running / unable to listen on socket errors. But it makes sense, as upstart starts Unicorn when it is not running, and then capistrano-unicorn is also attempting to start Unicorn.

I have now combined these capistrano tasks and hooks with Monit and a Unicorn init script.

Capistrano tasks:

namespace :monit do
  desc ' wait 20 seconds '
  task :wait_20_seconds do
    sleep 20
  end
  task :monitor_all, :roles => :app do
    sudo "monit monitor all"
  end

  task :unmonitor_all, :roles => :app do
    sudo "monit unmonitor all"
  end

  desc 'monitor unicorn in the monit rc file'
  task :monitor_unicorn, :roles => :app do
    sudo "monit monitor unicorn"
  end

  desc 'unmonitor unicorn in the monit rc file'
  task :unmonitor_unicorn, :roles => :app do
    sudo "monit unmonitor unicorn"
  end
end

Capistrano hooks:

after 'deploy:restart', 'unicorn:duplicate'  # app preloaded. check https://github.com/sosedoff/capistrano-unicorn section for zero downtime

before 'deploy', "monit:unmonitor_unicorn"
before 'deploy:migrations', "monit:unmonitor_unicorn"

after 'deploy', 'monit:wait_20_seconds'
after "deploy:migrations", "monit:wait_20_seconds"

after 'monit:wait_20_seconds', 'monit:monitor_unicorn'

I use Monit to monitor my unicorn process:

Within /etc/monit/monitrc:

check process unicorn
  with pidfile /var/www/apps/my_app/shared/pids/mypid.pid
  start program = "/usr/bin/sudo service unicorn start"
  stop program = "/usr/bin/sudo service unicorn stop"

Within your init script, you will start the unicorn process with something like: unicorn_rails -c /var/www/apps/my_app/current/config/unicorn.rb -E staging -D Make sure the -E flag is set to the correct environment. The capistrano-unicorn gem has directives using :set within deploy.rb which allow you to specify the environment for that unicorn process.

Upvotes: 0

Related Questions