Windows で生成された Ruby プロジェクトのデプロイ
最終更新日 2016年01月06日(水)
Table of Contents
Heroku のスタックは Linux のディストリビューションで実行されるため、インストールされるすべてのライブラリが Linux 互換である必要があります。Windows マシンで開発している場合、OS 間の依存関係の互換性問題が原因で、Linux へのデプロイ時に問題が発生することがあります。Mac または別の Linux ディストリビューションの開発者には、以下で説明する問題は当てはまりません。
背景: 依存関係の解決
Ruby アプリケーションを開発している場合、Gemfile
を使用して必要な依存関係を宣言します。bundle install
を実行すると、すべての依存関係が評価され、解決できるかどうかが確認されます。次に、Bundler により Gemfile.lock
が作成されます。このファイルには、インストールされた依存関係の正確なバージョンが含まれているため、同じ Gemfile
と Gemfile.lock
を別のコンピューター上の誰かに渡して bundle install
を実行させると、まったく同じバージョンがインストールされます。
一部の gem では、Windows との互換性を維持するために特別なバージョンを作成することを決定しました。Windows マシンで bundle install
を実行すると、次のような内容が Gemfile.lock
に含まれている場合があります。
PLATFORMS
ruby
x86-mingw32
この x86-mingw32
行は、Gemfile
が Windows マシン上で評価されたことを Bundler に知らせます。mingw
の部分が mswin
になっている場合もあります。個別の gem に特別なマーカーが含まれていることにお気付きかもしれません。
sqlite3 (1.3.8-x86-mingw32)
これは、この gem がプラットフォーム x86-mingw32
または Windows 向けのカスタム版であることを示しています。
Heroku スタックは Linux ベースのため、このタイプの gem は Heroku では実行されません。 この問題のため、以前の Gemfile.lock
の解決は破棄して、ゼロから bundle install
を実行する必要があります。
lockfile なしでのバンドルインストール
bundle install
を実行する前に Gemfile.lock
が削除されると、ライブラリとそのインストール済みバージョンの履歴がすべて失われます。Bundler のリゾルバーでは、新しい Gemfile.lock
を再生成して gem をインストールする作業が必要になります。これには、開発コードと本番コードの不整合、そして Gemfile がまったく解決されない可能性という 2 つの問題があります。
検出
Heroku では、Windows 固有の Gemfile.lock
を検出すると、行に警告を出力します。デプロイ出力に次のような内容が含まれていないか確認してください。
Removing `Gemfile.lock` because it was generated on Windows.
開発と本番のパリティ不整合
Gemfile.lock
がない場合に、Gemfile に次のような行があるとします。
gem 'rails'
これは、どのバージョンの Rails をインストールしてもよいことを Bundler に指示しています。ローカルマシンに 3.2.x
がすでにインストールされていることを検出した場合はそのバージョンを使用する一方、インストール先が同僚のマシンの場合には 4.0.x
がインストールされるという状況になることがあります。
マシン間で、また開発と本番の間でこのような不整合があると、高確率でエラーが発生します。開発環境で再現できない奇妙な動作が本番環境で発生する場合があります。これを回避して開発と本番のパリティを実現するために、Gemfile の内容はできるだけ具体的にしてください。
gem 'rails', '4.0.1'
そうすれば、Gemfile.lock
がない場合でも Rails 4.0.1 のインストールが保証されます。すべての依存関係に対してこれを行うことは不可能ですが、以上 (>=
) や悲観的ロック (~>
) などの演算子 (なるべく後者) を使用して、gem 要件のスコープを制限することができます。
Gemfile の内容を具体的にすることのマイナス面は、1 つの gem をアップグレードすると gem の解決に失敗する場合があること、また、依存関係のバージョンを手動で宣言する方法を正しく突き止めるのに時間がかかる場合があることです。
Gemfile を解決できない
gem のバージョンがあいまいすぎる場合や、それらのライブラリに循環要件がある場合、依存関係を解決できないのに無限ループで試行し続けるという状態に Bundler が陥る可能性があります。bundle install
を実行した後、出力が何分間もフリーズしているように見える場合や、..........
のようにドットの連続が出力される場合は、Gemfile.lock
が削除されると Gemfile
を解決できないことの症状である可能性があります。このシナリオでは、Bundler での処理を容易にして検索範囲を絞り込むために、gem バージョンの要件をより具体的にする必要があると考えられます。
対策
Windows で開発するときは、Gemfile の内容をできるだけ具体的にしてください。チームで Windows マシンを使用している開発者が 1 人だけの場合は、その開発者による Gemfile.lock
の変更をチェックインしないこと、または、デプロイの前に Windows 以外のマシンでバンドルを手動でインストールおよびコミットすることを検討してください。