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

2015-10-27

Jekyll を Cloud Foundry で動かす

「Cloud Foundry 百日行」第87日目,今日から3日間は,少し趣向を変えて「静的サイト・ジェネレーター」を Cloud Foundry 上で動かしてみたいと思います。

「静的サイト」であれば,手元で生成して staticfile-buildpack を使えばそれで終わりなのですが,このシリーズでは生成も Cloud Foundry 上で行うという趣旨で, Jekyll, Hugo, Sphinx の3つを紹介していきます。

今回はまず,blog のツールとしても多く使われている Jekyll を取り上げます。

基本情報

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

  • 1) 静的サイトのサンプルの取得
  • 2) Cloud Foundry 向けの設定
  • 3) Cloud Foundry へのデプロイ
  • 4) 動作確認
  • 5) まとめ

1. 静的サイトのサンプルの取得

当たり前の話ですが,今回は Jekyll を Cloud Foundry にデプロイするわけではなく,Jekyll で生成したサイトをデプロイするので,生成対象のサンプルが必要です。もともとこの百日行シリーズの記事は Jekyll を使って HTML を生成していたので,今回はそこから冒頭の2記事をサンプルとして使うことにしました。

サンプルは GitHub に置いてあるので,試してみられる方は以下の手順で clone して,ディレクトリーを移動してください。

$ git clone https://github.com/nota-ja/cf-jekyll-example.git
..
$ cd cf-jekyll-example/

2. Cloud Foundry 向けの設定

今回のデプロイでは,

  • heroku-buildpack-ruby-jekyll でコンテンツを生成した後,
  • staticfile-buildpack で nginx を使って静的コンテンツを serve する

という方法をとります。

heroku-buildpack-ruby-jekyll 単体でも,Ruby の Web サーバーを使えば静的コンテンツの serve はできるのですが,

  • さまざまな方法を試したい
  • サーバーの性能的には nginx の方が有利

という考えで,こうなりました。

複数の buildpack を使うので, heroku-buildpack-multi も使います。

では,順次見ていきましょう。

2.1. heroku-buildpack-multi 用の設定

.buildpacks ファイルを作り,以下の内容を記述します。

$ cat .buildpacks
https://github.com/nota-ja/heroku-buildpack-ruby-jekyll#update
https://github.com/cloudfoundry/staticfile-buildpack

最初の buildpack は, heroku-buildpack-ruby-jekyll を fork して jekyll コマンド周りを更新したものです。

heroku 向けの Jekyll 用 buildpack は,上記も含め幾つか見つけたのですが,ステージング時にサイトの生成を行うシンプルなものは古いものが多く, 最新の jekyll gem ではエラーが起きてしまったので,fork してその部分だけ修正しました。修正したのは1行だけです。

$ git diff a4be7db dc20140
diff --git a/lib/language_pack/ruby.rb b/lib/language_pack/ruby.rb
index 5db862a..f3f2172 100644
--- a/lib/language_pack/ruby.rb
+++ b/lib/language_pack/ruby.rb
@@ -597,7 +597,7 @@ params = CGI.parse(uri.query || "")

   def generate_jekyll_site
     puts "Building jekyll site"
-    pipe("env PATH=$PATH bundle exec jekyll --no-server --no-auto 2>&1")
+    pipe("env PATH=$PATH bundle exec jekyll build 2>&1")
     unless $? == 0
       error "Failed to generate site with jekyll."
     end

2.2. staticfile-buildpack 用の設定

staticfile-buildpack を使うためには,detect スクリプトが成功するよう,Staticfile というファイルがディレクトリーのルートに存在する必要があります。通常は空のファイルが存在すれば良いのですが,jekyll コマンドでサイトを生成すると,_site というディレクトリー下にコンテンツが生成されるので,そこを serve するよう,staticfile-buildpack の機能を使って指定します。具体的には, staticfile-buildpack の README に従って,Staticfile 内に以下のような記述を行います。

$ cat Staticfile
root: _site

2.3. Staticfile を Jekyll のサイト生成対象から除外

この記事を読んでいる方の多くは Jekyll に慣れた方だと思うので,釈迦に説法ではあるかと思いますが,Jekyll はサイト生成の際,名前が _ 及び . で始まるもの以外の全てのファイル/ディレクトリーをサイト生成の対象にしようとします。したがって, bundle install を使って Gemfile 内の gem を vendor/bundle にインストールしてから jekyll でサイトの生成を行う今回のようなケースでは,vendor ディレクトリーや Gemfile, Gemfile.lock 等のファイルをサイト生成の対象から除外する必要があります。具体的には,_config.yml の exclude に除外対象のファイル/ディレクトリーの名前を記述しておきます。

今回,前項で新たに Staticfile というファイルを作りましたが,これも静的サイトとして serve するべきではないので,_config.yml の exclude にこれを追加します。

$ git diff -- _config.yml
diff --git a/_config.yml b/_config.yml
index efba535..8f716d5 100644
--- a/_config.yml
+++ b/_config.yml
@@ -16,4 +16,4 @@ markdown: kramdown
 kramdown:
   input: GFM

-exclude: [vendor, Gemfile, Gemfile.lock]
+exclude: [vendor, Gemfile, Gemfile.lock, Staticfile]

2.4. .cfignore の追加

ローカルで jekyll build を行ったりした場合,Cloud Foundry 上でのデプロイには不要なファイルが生成されます。これらをいちいちデプロイ前に削除するのも面倒なので,.cfignore ファイルを書いて cf push 時にアップロードされないようにします。

$ cat .cfignore
_site
.sass-cache
/vendor/bundle/
/.bundle/

3. Cloud Foundry へのデプロイ

以上で準備が整ったので,Cloud Foundry にデプロイします。Buildpack として heroku-buildpack-multi を指定するのを忘れないようにしてください。

$ cf push jekyll-example -b https://github.com/ddollar/heroku-buildpack-multi.git
Creating app jekyll-example in org nota-ja / space prod as nota-ja...
OK
..
1 of 1 instances running
 
App started
 
 
OK
 
App jekyll-example was started using this command `sh boot.sh`
 
Showing health and status for app jekyll-example in org nota-ja / space prod as nota-ja...
OK
 
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: jekyll-example.10.244.0.34.xip.io
last uploaded: Fri Oct 23 12:17:08 UTC 2015
stack: cflinuxfs2
 
     state     since                    cpu    memory        disk      details
#0   running   2015-10-23 09:19:24 PM   0.0%   24M of 256M   0 of 1G

起動しました。メモリはデフォルトの 256MB のままにしていますが,これより少なくても良さそうです。

4. 動作確認

ブラウザーでアクセスした時のトップ画面はこんな感じです:

各ページを表示させてみます:

画像も表示されていることを確認しました:

以上で動作確認は終わりです。

5. まとめ

「静的サイト・ジェネレーター」シリーズ第1弾,まずは Jekyll で生成したサイトをデプロイしてみました。

今回は heroku-buildpack-multi を使って nginx による serve を試しましたが,それほど負荷の大きくないサイトであれば,Ruby の Web サーバーを使った方がシンプルにデプロイできると思います。実際, このページの “Setting Up rack-jekyll” を参考にセットアップを行ってデプロイを試してみましたが,問題なく動作しました。文末にそのコミットへのリンクも記載しているので,興味のある方は試してみてください。

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