オープンソースのPaaSソフトウェア CloudFoundry の技術情報やイベント告知などを掲載します

2015-09-17

Milkode は Cloud Foundry で動かなかった

「Cloud Foundry 百日行」第63日目は,Ruby で書かれた行指向のソースコード検索エンジン/検索アプリ Milkode です。しかし,タイトルからわかるように,今回は残念ながら敗戦記です。

基本情報

手順の概要は以下の通りです。

  • 1) Milkode を使ったソースコードDBの作成
  • 2) Cloud Foundry 向けのちょっとした設定
  • 3) アプリのプッシュ
    • 3.1) そのままプッシュ (ステージング失敗)
    • 3.2) heroku-buildpack-groonga を使ったプッシュ (ステージング失敗)
    • 3.3) heroku-buildpack-rroonga を使ったプッシュ (ステージング失敗)
    • 3.4) heroku-buildpack-apt を使ったプッシュ (ステージング失敗)
  • 4) まとめ

1. Milkode を使ったソースコードDBの作成

Milkode はソースが公開されているオープンソースのアプリケーションですが, マニュアル を読むと,

  • Milkode を gem としてインストールし
  • 検索対象のソースコードに対してデータベースを作って
  • それを Web アプリで検索する

というのが一般的な使い方のようなので,今回はそれに合わせて Cloud Foundry 上へのデプロイを行うことにします。

まず Gemfile を作り,Milkode gem をインストールします。

$ emacs Gemfile
..
$ cat Gemfile
source 'https://rubygems.org'

ruby '2.2.2'

gem 'milkode'

Ruby のバージョンは,デプロイ先の Cloud Foundry 環境に含まれる ruby-buildpack のバージョン v1.4.2 のデフォルトである 2.2.2 を指定します。

$ cf buildpacks
Getting buildpacks...

buildpack              position   enabled   locked   filename
staticfile_buildpack   1          true      false    staticfile_buildpack-cached-v1.0.0.zip
java_buildpack         2          true      false    java-buildpack-v3.0.zip
ruby_buildpack         3          true      false    ruby_buildpack-cached-v1.4.2.zip
..

https://github.com/cloudfoundry/ruby-buildpack/blob/v1.4.2/CHANGELOG#L13

* Default Ruby version set to MRI 2.2.2

マニュアル を参考に,Milkode のデータベースを作成します。

ただし,作成したデータベースごと Cloud Foundry にアップロードする必要があるので,まずデータベースのパスを環境変数で指定したのち,データベースの作成を行います。

$ export MILKODE_DEFAULT_DIR=${PWD}/.milkode
$ bundle exec milk init

次に, データベースにパッケージを追加 します。今回は,Milkode 自身のソースコードを GitHub から取り込んでみます。

$ bundle exec milk add git://github.com/ongaeshi/milkode.git
git        : git://github.com/ongaeshi/milkode.git
Cloning into '/home/nota-ja/repos/milkode/.milkode/packages/git/milkode'...
remote: Counting objects: 9928, done.
remote: Total 9928 (delta 0), reused 0 (delta 0), pack-reused 9928
Receiving objects: 100% (9928/9928), 5.59 MiB | 1.57 MiB/s, done.
Resolving deltas: 100% (4269/4269), done.
Checking connectivity... done.
package    : milkode
github     : ongaeshi/milkode
result     : 1 packages, 148 records, 148 add. (6.24sec)
*milkode*  : 1 packages, 148 records in /home/nota-ja/repos/milkode/.milkode/db/milkode.db.

以上でデータベースの作成が終わりました。

ちなみにこの段階で,ローカルで Milkode の Web アプリを起動することができるようになっているはずです。実際に起動してみると,localhost の 9292 ポートを listen します。

$ bundle exec milk web --no-browser
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 127.0.0.1:9292, CTRL+C to stop

Web ブラウザーでアクセスすると,以下のような画面が出てきて,動いていることがわかります。

2. Cloud Foundry 向けのちょっとした設定

このままプッシュするとかなりデータ量が多くなってしまうので,少しでもアップロードするファイルを少なくするために .cfignore ファイルを作っておきます。

$ emacs .cfignore
..
$ cat .cfignore
.git/
vendor/

以上で Cloud Foundry にデプロイする準備が整いました。

3. アプリのプッシュ

以下は失敗の記録です。色々なパターンで試したのですが,全てステージングで失敗しました。症状としては, bundle install で gem をインストールしている最中に一定時間止まって,その後失敗するというパターンです。原因を特定してはいませんが,インストールに成功した gem の中に一度も rroonga の名前が出てきていないことを考えると,rroonga gem のインストールに失敗している可能性が大きいと思われます。

3.1. そのままプッシュ (ステージング失敗)

まずはこの状態でプッシュしてみました。

$ cf push milk -c 'bundle exec milk web -o $VCAP_APP_HOST -p $VCAP_APP_PORT --no-browser'
Creating app milk in org nota-ja / space 100 as nota-ja...
OK

Creating route milk.10.244.0.34.xip.io...
OK

Binding milk.10.244.0.34.xip.io to milk...
OK

Uploading milk...
Uploading app files from: /home/nota-ja/repos/milkode
Uploading 218.8M, 244 files
Done uploading
OK

Starting app milk in org nota-ja / space 100 as nota-ja...
-----> Downloaded app package (2.9M)
-------> Buildpack version 1.4.2
-----> Compiling Ruby/Rack
-----> Using Ruby version: ruby-2.2.2
-----> Installing dependencies using 1.9.7
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
       Fetching gem metadata from https://rubygems.org/...........
       Fetching version metadata from https://rubygems.org/...
       Fetching dependency metadata from https://rubygems.org/..
       Installing io-like 0.3.0
       Installing addressable 2.3.8
       Installing coderay 1.1.0
       Installing daemons 1.2.3
       Installing gqtp 1.0.6
       Installing tilt 2.0.1
       Installing highline 1.7.5
       Installing i18n 0.6.11
       Installing rack 1.6.4
       Installing pkg-config 1.1.6
       Installing sass 3.4.18
       Installing eventmachine 1.0.8
       Installing thor 0.19.1
       Using bundler 1.9.7
       Installing json 1.8.3
       Installing os 0.9.6
       Installing archive-zip 0.7.0
       Installing launchy 2.4.3
       Installing haml 4.0.7
       Installing termcolor 1.2.1
       Installing rack-protection 1.5.3
       Installing groonga-command 1.1.3
       Installing sane 0.25.8
       Installing thin 1.6.3
       Installing groonga-client 0.1.9
       Installing whichr 0.3.6
       Installing sinatra 1.4.6


FAILED
StagingError

TIP: use 'cf logs milk --recent' for more information

ステージングに失敗しました。 bundle install が途中で止まってしまったようです。

3.2. heroku-buildpack-groonga を使ったプッシュ (ステージング失敗)

ローカルで bundle install する際も (書いてはいませんでしたが) rroonga gem をインストールするために Groonga のインストールが必要だったので,これが原因ではないかと考えました。

調べてみたところ, Heroku用Groongaのビルド方法 という記事が見つかり,その中で heroku-buildpack-groonga が紹介されていたので,これと Cloud Foundry の ruby-buildpack を組み合わせてデプロイしてみることにしました。

複数の buildpack の組み合わせということで,いつもの heroku-buildpack-multi を使います。

.buildpacks ファイルを作って,

$ emacs .buildpacks
..
$ cat .buildpacks
https://github.com/groonga/heroku-buildpack-groonga.git
https://github.com/cloudfoundry/ruby-buildpack.git#v1.4.2

プッシュします。

$ cf push milk -c 'bundle exec milk web -o $VCAP_APP_HOST -p $VCAP_APP_PORT --no-browser' -b https://github.com/ddollar/heroku-buildpack-multi.git
Updating app milk in org nota-ja / space 100 as nota-ja...
OK

Uploading milk...
Uploading app files from: /home/nota-ja/repos/milkode
Uploading 649.9K, 218 files
Done uploading
OK

Stopping app milk in org nota-ja / space 100 as nota-ja...
OK

Starting app milk in org nota-ja / space 100 as nota-ja...
-----> Downloaded app package (2.9M)
Cloning into '/tmp/buildpacks/heroku-buildpack-multi'...
=====> Downloading Buildpack: https://github.com/groonga/heroku-buildpack-groonga.git
Staging failed: Buildpack compilation step failed

FAILED
BuildpackCompileFailed

bundle install に行く前に,heroku-buildpack-groonga の処理で失敗してしまいました。おそらく使っているバイナリが Heroku の環境でビルドされたものであるため,Cloud Foundry の環境に適合しなかったのではないかと推測しています。

3.3. heroku-buildpack-rroonga を使ったプッシュ (ステージング失敗)

さきに挙げた Heroku用Groongaのビルド方法 の中で,関連記事として HerokuでRroongaを使う方法 へのリンクがありました。その記事では heroku-buildpack-rroonga の使い方について触れていたので,今度はそれを使ってみることにしました。ただし記事を読む限りでは heroku-buildpack-rroonga = heroku-buildpack-groonga + heroku-buildpack-ruby と思われたので,望み薄だと考えてはいました。

$ emacs .buildpacks
..
$ cat .buildpacks
https://github.com/groonga/heroku-buildpack-rroonga.git
https://github.com/cloudfoundry/ruby-buildpack.git#v1.4.2

プッシュします。

$ cf push milk -c 'bundle exec milk web -o $VCAP_APP_HOST -p $VCAP_APP_PORT --no-browser' -b https://github.com/ddollar/heroku-buildpack-multi.git
Updating app milk in org nota-ja / space 100 as nota-ja...
OK

Uploading milk...
Uploading app files from: /home/nota-ja/repos/milkode
Uploading 650K, 219 files
Done uploading
OK

Stopping app milk in org nota-ja / space 100 as nota-ja...
OK

Starting app milk in org nota-ja / space 100 as nota-ja...
-----> Downloaded app package (2.9M)
Cloning into '/tmp/buildpacks/heroku-buildpack-multi'...
=====> Downloading Buildpack: https://github.com/groonga/heroku-buildpack-rroonga.git
Staging failed: Buildpack compilation step failed

FAILED
BuildpackCompileFailed

TIP: use 'cf logs milk --recent' for more information

heroku-buildpack-groonga の時と同じ結果でした。

3.4. heroku-buildpack-apt を使ったプッシュ (ステージング失敗)

Groonga がインストールされていればいいのであれば, heroku-buildpack-apt を使うことも考えられます。最後にそれを試してみることにしました。

まず,.buildpacks を更新します。

$ emacs .buildpacks
..
$ cat .buildpacks
https://github.com/ddollar/heroku-buildpack-apt.git
https://github.com/cloudfoundry/ruby-buildpack.git

heroku-buildpack-multi が Git の submodule に対応していないので,ここでは submodule を使用していない Cloud Foundry の ruby-buildpack として,最新版を使いました。

3.4.1. groonga deb パッケージを指定

groonga の公式サイトのドキュメント には,Ubuntu にインストールする場合は [groonga] パッケージを使え,とあるので,heroku-buildpack-apt の設定ファイルである Aptfile でそれを指定します。

$ emacs Aptfile
..

$ cat Aptfile
http://packages.groonga.org/ubuntu/pool/trusty/universe/g/groonga/groonga_4.0.1-1_amd64.deb

groonga deb パッケージは Ubutu 標準のパッケージ・リポジトリーには含まれていないので,deb ファイルを直接指定しました。

プッシュします。

$ cf push milk -c 'bundle exec milk web -o $VCAP_APP_HOST -p $VCAP_APP_PORT --no-browser' -b https://github.com/ddollar/heroku-buildpack-multi.git
Updating app milk in org nota-ja / space 100 as nota-ja...
OK

Uploading milk...
Uploading app files from: /home/nota-ja/repos/milkode
Uploading 650.3K, 220 files
Done uploading
OK

Stopping app milk in org nota-ja / space 100 as nota-ja...
OK

Starting app milk in org nota-ja / space 100 as nota-ja...
-----> Downloaded app package (2.9M)
Cloning into '/tmp/buildpacks/heroku-buildpack-multi'...
=====> Downloading Buildpack: https://github.com/ddollar/heroku-buildpack-apt.git
=====> Detected Framework: Apt
-----> Updating apt caches
       Ign http://archive.ubuntu.com trusty InRelease
       Ign http://archive.ubuntu.com trusty-updates InRelease
       Get:1 http://archive.ubuntu.com trusty Release.gpg [933 B]
       Get:2 http://archive.ubuntu.com trusty-updates Release.gpg [933 B]
       Get:3 http://archive.ubuntu.com trusty Release [58.5 kB]
       Get:4 http://archive.ubuntu.com trusty-updates Release [63.5 kB]
       Get:5 http://archive.ubuntu.com trusty/main amd64 Packages [1,743 kB]
       Ign http://security.ubuntu.com trusty-security InRelease
       Get:6 http://security.ubuntu.com trusty-security Release.gpg [933 B]
       Get:7 http://security.ubuntu.com trusty-security Release [63.5 kB]
       Get:8 http://security.ubuntu.com trusty-security/main amd64 Packages [433 kB]
       Get:9 http://security.ubuntu.com trusty-security/universe amd64 Packages [150 kB]
       Get:10 http://archive.ubuntu.com trusty/universe amd64 Packages [7,589 kB]
       Get:11 http://security.ubuntu.com trusty-security/multiverse amd64 Packages [3,528 B]
       Get:12 http://archive.ubuntu.com trusty/multiverse amd64 Packages [169 kB]
       Get:13 http://archive.ubuntu.com trusty-updates/main amd64 Packages [779 kB]
       Get:14 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [407 kB]
       Get:15 http://archive.ubuntu.com trusty-updates/multiverse amd64 Packages [12.9 kB]
       Fetched 11.5 MB in 40s (286 kB/s)
       Reading package lists...
-----> Fetching http://packages.groonga.org/ubuntu/pool/trusty/universe/g/groonga/groonga_4.0.1-1_amd64.deb
-----> Installing groonga_4.0.1-1_amd64.deb
-----> Writing profile script
=====> Downloading Buildpack: https://github.com/cloudfoundry/ruby-buildpack.git
=====> Detected git submodules. Initializing...
Submodule 'compile-extensions' (https://github.com/cloudfoundry/compile-extensions) registered for path 'compile-extensions'
Cloning into 'compile-extensions'...
Submodule path 'compile-extensions': checked out 'b5e0cf7be729718d162d56709ec7f27d34e68c7c'
=====> Detected Framework: ruby 1.6.7
-------> Buildpack version 1.6.7
-----> Compiling Ruby/Rack
-----> Using Ruby version: ruby-2.2.2
-----> Installing dependencies using 1.9.7
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
       Fetching gem metadata from https://rubygems.org/...........
       Fetching version metadata from https://rubygems.org/...
       Fetching dependency metadata from https://rubygems.org/..
       Installing io-like 0.3.0
       Installing addressable 2.3.8
       Installing coderay 1.1.0
       Installing daemons 1.2.3
       Installing gqtp 1.0.6
       Installing tilt 2.0.1
       Installing highline 1.7.5
       Installing i18n 0.6.11
       Installing rack 1.6.4
       Installing pkg-config 1.1.6
       Installing sass 3.4.18
       Installing thor 0.19.1
       Installing eventmachine 1.0.8
       Using bundler 1.9.7
       Installing json 1.8.3
       Installing os 0.9.6
       Installing archive-zip 0.7.0
       Installing launchy 2.4.3
       Installing haml 4.0.7
       Installing termcolor 1.2.1
       Installing rack-protection 1.5.3
       Installing groonga-command 1.1.3
       Installing thin 1.6.3
       Installing sane 0.25.8
       Installing sinatra 1.4.6
       Installing groonga-client 0.1.9
       Installing whichr 0.3.6

FAILED
StagingError

TIP: use 'cf logs milk --recent' for more information

groonga deb パッケージのイントールには成功したようですが,最初と同様に bundle install の途中で失敗しました。

3.4.2. libgroonga-dev deb パッケージを指定

別に見つけたこの Groonga の中の人が書いていると思われる記事 で, [libgroonga-dev] パッケージを使う方法が紹介されていたので,最後の挑戦としてそれを試すことにしました。

Aptfile を更新します。

$ emacs Aptfile
..

$ cat Aptfile
http://packages.groonga.org/ubuntu/pool/trusty/universe/g/groonga/libgroonga-dev_4.0.1-1_amd64.deb

プッシュしてみます。

$ cf push milk -c 'bundle exec milk web -o $VCAP_APP_HOST -p $VCAP_APP_PORT' -b https://github.com/ddollar/heroku-buildpack-multi.git
Updating app milk in org nota-ja / space 100 as nota-ja...
OK

Uploading milk...
Uploading app files from: /home/nota-ja/repos/milkode
Uploading 650.5K, 221 files
Done uploading
OK

Stopping app milk in org nota-ja / space 100 as nota-ja...
OK

Starting app milk in org nota-ja / space 100 as nota-ja...
-----> Downloaded app package (2.9M)
Cloning into '/tmp/buildpacks/heroku-buildpack-multi'...
=====> Downloading Buildpack: https://github.com/ddollar/heroku-buildpack-apt.git
=====> Detected Framework: Apt
-----> Updating apt caches
       Ign http://archive.ubuntu.com trusty InRelease
       Ign http://security.ubuntu.com trusty-security InRelease
       Ign http://archive.ubuntu.com trusty-updates InRelease
       Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
       Get:2 http://archive.ubuntu.com trusty Release.gpg [933 B]
       Get:3 http://security.ubuntu.com trusty-security Release [63.5 kB]
       Get:4 http://archive.ubuntu.com trusty-updates Release.gpg [933 B]
       Get:5 http://archive.ubuntu.com trusty Release [58.5 kB]
       Get:6 http://security.ubuntu.com trusty-security/main amd64 Packages [433 kB]
       Get:7 http://archive.ubuntu.com trusty-updates Release [63.5 kB]
       Get:8 http://archive.ubuntu.com trusty/main amd64 Packages [1,743 kB]
       Get:9 http://security.ubuntu.com trusty-security/universe amd64 Packages [150 kB]
       Get:10 http://security.ubuntu.com trusty-security/multiverse amd64 Packages [3,528 B]
       Get:11 http://archive.ubuntu.com trusty/universe amd64 Packages [7,589 kB]
       Get:12 http://archive.ubuntu.com trusty/multiverse amd64 Packages [169 kB]
       Get:13 http://archive.ubuntu.com trusty-updates/main amd64 Packages [779 kB]
       Get:14 http://archive.ubuntu.com trusty-updates/universe amd64 Packages [407 kB]
       Get:15 http://archive.ubuntu.com trusty-updates/multiverse amd64 Packages [12.9 kB]
       Fetched 11.5 MB in 13s (859 kB/s)
       Reading package lists...
-----> Fetching http://packages.groonga.org/ubuntu/pool/trusty/universe/g/groonga/libgroonga-dev_4.0.1-1_amd64.deb
-----> Installing libgroonga-dev_4.0.1-1_amd64.deb
-----> Writing profile script
=====> Downloading Buildpack: https://github.com/cloudfoundry/ruby-buildpack.git
=====> Detected git submodules. Initializing...
Submodule 'compile-extensions' (https://github.com/cloudfoundry/compile-extensions) registered for path 'compile-extensions'
Cloning into 'compile-extensions'...
Submodule path 'compile-extensions': checked out 'b5e0cf7be729718d162d56709ec7f27d34e68c7c'
=====> Detected Framework: ruby 1.6.7
-------> Buildpack version 1.6.7
-----> Compiling Ruby/Rack
-----> Using Ruby version: ruby-2.2.2
-----> Installing dependencies using 1.9.7
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
       Fetching gem metadata from https://rubygems.org/...........
       Fetching version metadata from https://rubygems.org/...
       Fetching dependency metadata from https://rubygems.org/..
       Installing addressable 2.3.8
       Installing coderay 1.1.0
       Installing io-like 0.3.0
       Installing daemons 1.2.3
       Installing gqtp 1.0.6
       Installing tilt 2.0.1
       Installing highline 1.7.5
       Installing i18n 0.6.11
       Installing rack 1.6.4
       Installing pkg-config 1.1.6
       Installing sass 3.4.18
       Installing thor 0.19.1
       Installing os 0.9.6
       Using bundler 1.9.7
       Installing launchy 2.4.3
       Installing eventmachine 1.0.8
       Installing json 1.8.3
       Installing archive-zip 0.7.0
       Installing haml 4.0.7
       Installing termcolor 1.2.1
       Installing rack-protection 1.5.3
       Installing sane 0.25.8
       Installing groonga-command 1.1.3
       Installing thin 1.6.3
       Installing sinatra 1.4.6
       Installing whichr 0.3.6
       Installing groonga-client 0.1.9

FAILED
StagingError

TIP: use 'cf logs milk --recent' for more information

結果は変わらず, bundle install の途中で失敗しました。

4. まとめ

ということで,今回の試みは全て失敗に終わりました。 Cloud Foundry でデプロイが難しいアプリのパターンの一つとして,「特別なライブラリーを使う」というのが有りそうです。

今回のアプリは Heroku にはデプロイできるということなので, このページ に書かれているのと同様の手順を実施して Cloud Foundry 用の Groonga をビルドすれば,Cloud Foundry で動かすことができるようになる可能性はありそうです。しかし今回は時間切れでということで,ここまでにさせていただこうと思います。

もし「Milkodeをどうしても Cloud Foundry で動くようにしてほしい」という要望や,「こうしたら Milkode が動いた」という知見があれば,Twitter で @nota_ja に mention を飛ばしていただければと思います。

今回使用したソフトウェア