不自由なデプロイを強いられてる人のための Capistrano-env ってgemを作った

capistrano-env ってgemを作った

不自由なデプロイを強いられているんだッ

すべての人間は大きく2種類に分割でき、それは自由なデプロイを許された人間と、不自由なデプロイを強いられた人間です。

不自由なデプロイを強いられる環境とは次のような環境のことをいいます。

  • 自動デプロイとかDevOpsとかの文化がない
  • 特定の人しかデプロイの権限がない
  • その特定の人が現代的なクラウド文化を知らない
  • 偉い人が手動神話を信仰している
  • システムを動かすのに絶対必須な情報を開発者が知ってはいけない

以上はすべて妄想ですがもしかしたらこんな組織が実在するのかもしれません。 世の中には非常に便利なデプロイツールがあるのにこのような組織では上手く使うことが出来ません。

このgemはこのような不自由なデプロイを駆逐し、自由なデプロイの尖兵として賭けの攻勢に出るための武器です。

秘密情報という曲者

組織によっては開発者が知ってはいけない情報が設定されている場合があります。 DBサーバのパスワードやSALTなど、まあこのへんは納得できるんですが、 自分たちのAPIサーバのドメイン名を知らなかったり、何台のサーバで動いてるのかすら知ってはいけない、 なんて組織がもしかしたらあるかもしれません。

このあたりの情報は普通 config/database.yml とかに書いてリポジトリにコミットするわけですが、 秘密情報を含むファイルは作れないのでコミットできないことになります。 以前はどのようにしていたかというと、 config/database.yml.template とかのファイルをコミットし、 ローカルやテスト環境ではそれを config/database.yml にリネームするし、 本番にデプロイするときはインフラ担当が 手動で 正しい情報に書き換えて配置します。

はいこんな思想で自動化できるわけがないですよね。 それどころかフレームワーク標準のファイルが存在しないという状況は開発者のCIすら阻害されてしまいます。

heroku的解決

設定をコードから分離するための仕組みとして、 herokuにはアプリケーションごとにconfigが設定できるようになってます。 アプリケーションからは環境変数を通してその値にアクセスできます。

1
heroku config:set FOO=123

こんなかんじに設定すると

1
ENV['FOO'] # => 123

でアクセスできます。便利! これなら同じコードを全く変更すること無く別のherokuアプリケーションとして動かすこともできますね。

capistranoでENV設定

capistranoでデプロイするときに、環境変数付きでサーバを起動することができます。

1
set :default_environment, ENV.select{ |k,v| k =~ /^MYAPP_/ }

とか書けば MYAPP_ から始まる環境変数を全部デプロイ時に渡すことができます。 アプリ側は ymlファイルの値が書いてある部分を <%= ENV['MYAPP_XXX'] %> とかに置き換えて、 ymlを読む前に一回 Erb を通すようにすれば完成です。

これでデプロイ担当者のマシンに環境変数を設定し、 そのマシンからcapistranoで自動化されたデプロイができるようになりました。

develop/test/staging なんかの環境は別に秘密じゃないとおもうのでymlに即値で書いてしまいましょう。

unicornリスタート問題

unicornは一瞬もサービスが途切れること無くサーバのリスタートができるのが特徴ですが、 これはシグナルを送ることによって実現しているので、 ENVを使った場合はリスタートしても設定の変更ができない という問題があります。

ENVを更新しようとすると一旦unicornをstopしてstartしなくてはいけません。 これではunicornの良さが損なわれるのでなるべくやりたくない方法です。

ここまで辿り着いた段階でもう既存の方法では厳しいと思いgemを作りました。

capisrano-env がやっていること

やってることは単純です。 環境変数を付けてデプロイするのをやめて、 代わりに 環境変数を設定するファイル(コード) を一緒にデプロイします。 unicornをリスタートする前にも環境変数ファイルを毎回デプロイします。 動かすアプリケーションがRailsの場合は、 勝手にそのファイルを読み込んでrailsのブート中に環境変数を書き換えます。 config/application.rb などでymlの読み込みを始める前にはすでに環境変数が設定された状態になっています。

環境変数を設定するコードを実行するっていう気持ち悪さはありますが、 不自由な環境にいながら自動デプロイで幸せになるためにはこの方法しか考えられませんでした。 まぁ不自由な環境が実在するかどうかは定かではありませんが。

使いかた

deploy.rb

1
2
3
4
5
require 'capistrano-env'

capenv.use do |env|
  env.add /^MYAPP_/
end

ここまで書いててこれ自分で設定しなくて default_environment 拾ってくればいいんじゃねえのと思った

あと環境変数を設定するコードを吐く部分はフォーマッタって形で切り出してるから PhpFormatter とか作りたい人作っていいよ