OneDay

40歳からプログラマとして生活しています。

Capistrano3 S3 環境変数の引き渡し CarrierWave Wheneverの設定

バックアップファイルとアプリケーションの写真の保存先としてS3を利用している。

デプロイ時に環境変数がないよ、と言われる例。

Capistrano3でProduction環境へデプロイする際にCarrierWaveに

#config/initializer/carrierwave.rb
config.fog_credentials = {
    provider:              'AWS',                      
    aws_access_key_id:     ENV['AWS_ACCESS_KEY_ID'],            
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],     
    region:                ENV['AWS_REGION']      
}

上記の記載をしてbundle exec cap production deployすると

ArgumentError: Missing required arguments: aws_access_key_id, aws_secret_access_key

と怒られる。自分のPCにもサーバー側にも環境変数をセットしているのにエラーでデプロイの処理が進まない。これらの環境変数は読み込んでくれない。

config/deploy.rbの:default_envにセットすることで、自分のPCの環境変数をデプロイ時に読み込んでくれる。

(省略)
set :default_env, {
	rbenv_root: "/usr/local/rbenv",
	path: "~/.rbenv/shims:~/.rbenv/bin:$PATH",
	AWS_REGION: ENV['AWS_REGION'],
	AWS_ACCESS_KEY_ID: ENV["AWS_ACCESS_KEY_ID"],
        AWS_SECRET_ACCESS_KEY: ENV["AWS_SECRET_ACCESS_KEY"]
}
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }
set :sidekiq_queue, :carrierwave
(省略)

これを記載するとデプロイ時、下記のようにセットした環境変数が入って、デプロイ処理は進む。

Command: cd /var/www/app/releases/20151007055157 && ( RBENV_ROOT=~/.rbenv PATH=~/.rbenv/shims:~/.rbenv/bin:$PATH AWS_REGION=ap-northeast-1 AWS_ACCESS_KEY_ID=***************** AWS_SECRET_ACCESS_KEY=****************** RBENV_VERSION=2.1.0 RAILS_ENV=production ~/.rbenv/bin/rbenv exec bundle exec rake assets:precompile )


パーフェクト Ruby on Railsのp307に設定項目の説明があり、:default_envについて

デプロイタスク内での環境変数で、特別なものを指定できます。



次はwhenever(Capifileにはrequire 'whenever/capistrano'入れている)。AWS S3にバックアップ保存のタスクをwheneverでcron登録したいが、エラーが出る場合の対処法。

Aws::Errors::MissingRegionError: missing region; use :region option or export region name to ENV['AWS_REGION']

自分のPCやサーバーの環境変数が渡せてないようだ。タスクファイルを作って実験した。

#config/schedule.rb
set :output, 'log/crontab.log'
rails_env = ENV['RAILS_ENV'] || :production
set :environment, "#{rails_env}"
env :AWS_REGION, ENV['AWS_REGION']

job_type :rbenv_production,  "cd :path && :environment_variable=:environment bundle exec rake :task --silent :output"

if rails_env.to_sym == :production
  env :LOGIN_PATH, "amazon"
  every 1.minutes do
      rbenv_production "deploy_test"
  end
end
#test_task.rake
desc "deploy test to pass environmental variables"
task :deploy_test do
    puts "test1 環境変数 あり deploy.rb あり schedule.rb   env :AWS_REGION, ENV['AWS_REGION'] --> #{ENV['AWS_REGION']}"
    puts "test2 環境変数 あり deploy.rb あり schedule.rb なし --> #{ENV['AWS_REGION2']}"
    puts "test3 環境変数 なし deploy.rb なし schedule.rb  env :LOGIN_PATH, 'amazon'-->#{ENV['LOGIN_PATH']}"
    puts "test4 環境変数 なし deploy.rb なし schedule.rb なし -->#{ENV['AMAZON']}"
end

出力結果

#log/crontab.log
test1 環境変数 あり deploy.rb あり schedule.rb   env :AWS_REGION, ENV['AWS_REGION'] --> us-east-1
test2 環境変数 あり deploy.rb あり schedule.rb なし -->
test3 環境変数 なし deploy.rb なし schedule.rb  env :LOGIN_PATH, 'amazon'--> amazon
test4 環境変数 なし deploy.rb なし schedule.rb なし-->


この実験の結果から、capistrano/wheneverの環境変数の渡し方についてこう言える。

  • schedule.rbに"env :LOGIN_PATH, 'amazon'"などと直接記載すれば、wheneverデプロイ時の環境変数としてセットされる。
  • schedule.rbにPCの環境変数を呼び場合は、env :AWS_REGION, ENV['AWS_REGION']をセットすれば、(同上)セットされる。

  • schedule.rbにenv オプションの記載がなければ、(同上)セットされない。
  • サーバー側にセットしてある環境変数を記載しても読み込まない。