###

alias hbin me

Capistrano && dotenv

今天看到 Hooopo 分享了一篇使用 Heroku 设置环境变量方式来部署的文章写得很棒,有兴趣的朋友请移步:http://www.jianshu.com/p/a80bdfdabce5

文中提到的<The TWELVE-FACTOR>一书简直是软件开发之最佳典范,涵盖代码管理,配置管理,日志管理,持续发布,微服务,多线程/多进程,等等。我差不多每隔段时间就会打开这本书,焚香拜读,每次都会有很大收获。

上次看这本书时,我就对 III. Config 一章产生极大兴趣,于是在自己的 Sample App 中用上了.

但是,碰到一个问题,那就是使用 capistrano-sidekiq 部署 Sidekiq 时会报找不到环境变量,从而启动不了。

经过排查发现,其实是 capistrano-sidekiq 的问题。Capistrano 会维护一个 CommandMap,例如:

  {
    :sidekiq => ["rbenv exec", "bundle exec"]
    :sidekiqctl => ["rbenv exec", "bundle exec"]
  }

当 Capistrano 要执行某个命令的时候,只要调用 SSHKit::Command#to_s 方法,从 CommandMap 中取到对应的命令就可以了。

回到我们 dotenv 的部署方式。由于 Rails 应用声明了 Dotenv::Railtie.load,所以可以顺利加载到 .env 文件;但 sidekiq 却不可以,不过 dotenv-rails 提供了另一种选择,就是 dotenv 命令:

1
bundle exec dotenv sidekiq -C config/sidekiq.yml

但是在 v0.5.3 版本的 capistrano-sidekiq 中,执行的命令被写死了。这里正确的写法应该是将 sidekiqsidekiqctl 命令增加到 bundle_bins 里,因此我提了一个 PR 给作者。在最新的版本里,这个 PR 也已经被 Merge 了。

最后,我们只要把 dotenv 命令也增加到上面的 CommandMap 里就可以了:

  # https://github.com/hbin/sample_app/blob/master/config%2Fdeploy.rb#L28-L34
  namespace :bundler do
    task :map_bins do
      fetch(:bundle_bins).each do |command|
        SSHKit.config.command_map.prefix[command.to_sym].push('dotenv')
      end
    end
  end

再使用 Capistrano 启动 Sidekiq 的时候,生成的命令就会是:

1
~/.rbenv/bin/rbenv exec bundle exec dotenv sidekiq --index 0 --pidfile /var/www/sample_app_production/shared/tmp/pids/sidekiq-0.pid --environment production --logfile /var/www/sample_app_production/shared/log/sidekiq.log --daemon as deploy@sample.com

到这里,算是把 dotenv 方式部署完全走通了。

Done.

Comments