Herokuで .NET(Mono)とRubyのbuildpackを使って、Nancyを起動しつつRakeタスクを実行する

以前、Herokuにて.NETのbuildpackを使ってNancyをデプロイしてみました。
C# + NancyでJSONを返すWebアプリを作り、Heroku Buttonを使ってHerokuへデプロイしてみた - メモ的な思考的な

 
そんな中、.NET(Mono)環境でもRakeタスクを使いたくなったため、いろいろと試してみた時のメモを残します。

 

環境

 

流れ

HerokuのMono環境にて、Rubyの確認

HerokuにNancyアプリをデプロイした時は、Monoのbuildpackを使っていました。

ただ、その状態ではRubyは動作しているようですが、gemは何もインストールされていませんでした。

$ heroku run ruby -v --app (AppName)
Running `ruby -v` attached to terminal... up, run.1735
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
 
$ heroku run gem list --app (AppName)
Running `gem list` attached to terminal... up, run.6192

*** LOCAL GEMS ***

 
当然ながら、Rakeを実行しようとしてもエラーになります。

$ heroku run rake --app (AppName)
Running `rake` attached to terminal... up, run.1763
bash: rake: command not found

 
また、新しくgemをインストールしようとしても、実行できませんでした。

$ heroku run gem install rake --app (AppName)
Running `gem install rake` attached to terminal... up, run.4633
Fetching: rake-10.4.2.gem (100%)
ERROR: While executing gem ... (Errno::EROFS)
  Read-only file system - /var/lib/gems

 

HerokuにMono環境とRuby環境を用意

以上より、Mono環境だけではRakeタスクを実行できませんでした。

そこで、何か良い方法がないかを探したところ、複数の言語を利用できるようになるheroku-buildpack-multiを使い、MonoとRubyの2つの環境を用意すれば良さそうでした。
Ruby - Herokuのapp作成手順(buildpack-multiを使う場合も含む) - Qiita

 

.buildpacksファイルの用意

heroku-buildpack-multiを使うため、.buildpacksファイルを用意します。

その中では、 heroku-buildpack-rubyheroku-buildpack-monoのbuildpackを使用するように指定します。

https://github.com/heroku/heroku-buildpack-ruby.git
https://github.com/friism/heroku-buildpack-mono.git

 

GemfileGemfile.lockの用意

heroku-buildpack-rubyによるRuby環境を構築する場合、GemfileGemfile.lockがないと、それぞれ次のようなエラーが発生します。

Gemfileがない場合

remote: =====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-ruby.git
remote:
remote: ! Push rejected, failed to compile Multipack app
remote:
remote: Verifying deploy...

 
Gemfile.lockがない場合

remote: =====> Detected Framework: Ruby
remote: -----> Compiling Ruby/NoLockfile
remote: !
remote: ! Gemfile.lock required. Please check it in.
remote: !
remote:
remote: ! Push rejected, failed to compile Multipack app

 
buildpackのFlowに次のように書かれていたため、エラーになったのかなと思いました。

Ruby (Gemfile and Gemfile.lock is detected)
heroku/heroku-buildpack-ruby · GitHub

 
そのため、まずは以下の内容を持つGemfileを作ります。

source 'https://rubygems.org'

 
続いて、Gemfile.lockを作成するため、bundlerを実行します。

$ bundle install --path vendor/bundle
...
It was installed into ./vendor/bundle

 

Gitへコミット
  • .buildpacks
  • Gemfile
  • Gemfile.lock

をGitリポジトリへとコミットします。

 

Herokuの環境変数を追加

heroku-buildpack-multiを使うために、BUILDPACK_URLへheroku/heroku-buildpack-multiのリポジトリのURLを環境変数へ追加します。

$ heroku config:add BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-multi.git

 

Herokuへpush

$ git push heroku master
...
remote: Verifying deploy... done.

 

Rubyとgemを確認

Rakeが入っています。

$ heroku run ruby -v
Running `ruby -v` attached to terminal... up, run.9263
ruby 2.0.0p598 (2014-11-13 revision 48408) [x86_64-linux]
 
$ heroku run gem list
Running `gem list` attached to terminal... up, run.2250
 
*** LOCAL GEMS ***
 
bigdecimal (1.2.0)
bundler (1.6.3)
io-console (0.4.2)
json (1.7.7)
minitest (4.3.2)
psych (2.0.0)
rake (0.9.6)
rdoc (4.0.0)
test-unit (2.0.0.0)

 

Rakefileの用意と実行

上記までで環境ができたため、今度はRakeタスクを用意します。

今回はコンソール画面にHello Worldを表示するRakeタスクを持つRakefileを作成します。

desc "Task Test"
task :hello do
  puts "Hello world"
end

 
上記のRakefileをコミット・Herokuへpushし、Rakeタスクを実行します。

$ heroku run rake hello
Running `rake hello` attached to terminal... up, run.9131
Hello world

問題なくRakeタスクが実行できました。

また、Nancyアプリも動作しています。

 

ソースコード

GitHubに上げておきました。
thinkAmi-sandbox/NancyOwinHeroku-rake

 
Heroku Buttonも置いておきます。

Deploy

 
なお、Nancyの部分はthinkAmi-sandbox/NancyOwinHeroku-sample · GitHub のコードをコピペして、必要なファイルを追加した形になっています。

 

その他

Windowsでgemをインストールしようとするとエラー

今回はGemfileがほぼ空っぽでしたが、何かgemを追加してbundle installすると、以下のようなエラーが発生することがあります。

$ bundle install --path vendor/bundle
DL is deprecated, please use Fiddle
Fetching source index from https://rubygems.org/
Retrying source fetch due to error (2/3): Bundler::Fetcher::CertificateFailureError Could not verify the SSL certificate for https://rubygems.org/.
There is a chance you are experiencing a man-in-the-middle attack, but most likely your system doesn't have the CA certificates needed for verification. For information about OpenSSL certificates, see bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile sources and change 'https' to 'http'.

 
あるいは、ローカルにgemをインストールしようとしてもエラーになります。

$ gem install bundler --no-ri --no-rdoc
ERROR: Could not find a valid gem 'bundler' (>= 0), here is why:
     Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/latest_specs.4.8.gz)

 
対応としては、httpsをhttpにするのではなく、以下を参考に新しい証明書ファイルをダウンロード・設定します。
Windowsでgem installするとSSLエラーが出る場合の解決策 - Qiita

なお、自分はデフォルトのインストール先でRubyInstallerを使っていますが、その場合は、以下のパスになっていました。

C:\Ruby21\lib\ruby\2.1.0\rubygems\ssl_certs

 

Heroku toolbeltを入れるとRubyが入るが、削除するとエラー

Heroku toolbeltをインストールすると、自分で入れたRubyInstaller2.1.5の他に、Ruby1.9.3p448もインストールされます。

このRubyを消してしまうとherokuコマンドが以下のエラーで動作しなくなりました。

$ heroku
/c/Heroku/bin/heroku: line 4: /path/to/ruby: No such file or directory
/c/Heroku/bin/heroku: line 4: exec: /path/to/ruby: cannot execute: No such file or directory