LoginSignup
26
24

More than 5 years have passed since last update.

CapistranoでUnicorn + nginx in Ubuntuにデプロイしたら環境変数が適用されない問題解決メモ

Posted at

CapistranoでVagrantにデプロイした際、なぜか設定したはずの環境変数が適用されなかった。それはserviceコマンドの挙動が原因だった。という話です。

経緯

おなじみRailscasts#335で紹介された方法で、いったんデプロイには成功した。

しかしその後、Raiscasts#337を参考にconfig/recipesにCapistranoの設定を分割してからVagrantで作った環境にデプロイしたところ、環境変数が読み込まれなかった。

大問題である。

環境変数には、他人には見られたくないAmazon S3のパスワードなどが入っている。asset_syncfogを使っているので、アプリケーションにはどうしても環境変数の設定が必要。これらを本番環境で動くサーバにセットせねばならない。

選択肢として、application.ymlにS3のパスワードなどを書いて、本番環境に置くという方法もある。だができれば本番環境上で作業したくない。全部Capistranoですませたい。どうすればよいか?

余談

ちなみに、複数サーバにCapistranoでデプロイするのはとても簡単。GithubのCapistrano Wikiにやり方が書いてある。
https://github.com/capistrano/capistrano/wiki/2.x-Multistage-Extension
以前はプラグインとして提供されていたらしいcapistrano-extはすでにcapistrano内に入っている。 なので、

deploy.rb
set :stages, %w(production vagrant)
set :default_stage, "vagrant"
require "capistrano/ext/multistage"

とするだけで、複数ステージにデプロイ可能。

config/deployディレクトリを作って

config/deploy/production.rb
server "1xx.xxx.xxx.xx", :web, :app, :db, primary: true
set :user, "katryo"
set :port, 10022 #22から変更した
set :deploy_to, "/home/#{user}/apps/#{application}"
config/deploy/vagrant.rb
server "localhost", :web, :app, :db, primary: true
set :user, "vagrant"
set :port, 2222
set :deploy_to, "/home/#{user}/apps/#{application}"

ssh_options[:keys] = [
  "#{ENV['HOME']}/.ssh/id_rsa",
  "#{ENV['HOME']}/.vagrant.d/insecure_private_key"
]

とdeployディレクトリに各サーバの設定を別々に書けばよい。参考:
http://d.hatena.ne.jp/okinaka/20120520/1337476743

set :deploy_toが重複していて気持ち悪いけど、読み込みのタイミング上、production.rbとvagrant.rbのuserが読み込まれてからdeploy_toを設定する必要があるのでしかたなく2回同じ文を書いた。

設定したはずの環境変数がなぜ適用されない?

Capistranoでは、

config/deploy.rb
ENV.update YAML.load(File.read(File.expand_path('../application.yml', __FILE__)))
set :default_environment, {
  "AWS_ACCESS_KEY_ID" => ENV["AWS_ACCESS_KEY_ID"],
  "AWS_SECRET_ACCESS_KEY" => ENV["AWS_SECRET_ACCESS_KEY"]
}

のように:default_environmentにsetすれば、シェルスクリプトを実行するrunの際に環境変数をセットできる。だから、開発環境の環境変数を引き継いで実行できる……はずだ。

この記事の環境変数の項でもそれについては説明した。 http://qiita.com/items/f410916d5314dad2de96

実際に、前回のデプロイでは環境変数の引き継ぎに成功した。なぜ今回に限って引き継ぎに失敗するのか?

前回の手法をもういちど試したところ、引き継ぎには成功。
前回と今回の違いはどこか? recipesにCapistranoの設定を分割したことか? 色々考え、調べたところ、原因が判明した。

原因

# storyblogはアプリケーション名
$ service unicorn_storyblog start

が原因だった。

service hoge startは環境変数をほぼ引き継がない!!!

serviceで起動した場合、環境変数はLANG, PATH, TERMの3つだけを適用する、らしい。"service /etc/init.d 違い"あたりで検索したところ、情報がいろいろ出てきた。

これらの記事を参考。
http://d.hatena.ne.jp/amari3/20111223/1324656530
http://linux.just4fun.biz/?%E9%80%86%E5%BC%95%E3%81%8DUNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%2F%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9(%E3%83%87%E3%83%BC%E3%83%A2%E3%83%B3)%E3%81%AE%E8%B5%B7%E5%8B%95%E3%83%BB%E5%86%8D%E8%B5%B7%E5%8B%95%E3%83%BB%E5%81%9C%E6%AD%A2%E3%83%BB%E7%8A%B6%E6%85%8B%E5%8F%96%E5%BE%97

解決方法

なので、Raiscasts#337のCapistrano設定コードを書きかえ、

config/recipes/unicorn.rb
run "service unicorn_#{application} #{command}"

となっている箇所を

config/recipes/unicorn.rb
run "/etc/init.d/unicorn_#{application} #{command}"

と書きかえ。

nginxに関しても

config/recipes/nginx.rb
run "#{sudo} service nginx #{command}"

となっているところを

config/recipes/nginx.rb
run "#{sudo} /etc/init.d/nginx #{command}"

と書きかえた。

$ capistrano vagrant unicorn:stop
$ capistrano vagrant unicorn:start

としたら、見事環境変数を読み込んでくれた。やった!!!! 半日悩んだ問題が解決した。

ちなみに最後のunicorn停止と起動に関して、再起動の

$ capistrano vagrant unicorn:restart

ではダメだった。Unicornはrestartの際、環境変数を引き継いで再起動するらしいのでそれが原因……なのかも。

ちょっと違うけど、参考。/etc/init.dからの起動時に環境変数を指定する方法 http://qiita.com/items/83bb3fb5cb7f46484d4b

26
24
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
26
24