「Cloud Foundry 百日行」第87日目,今日から3日間は,少し趣向を変えて「静的サイト・ジェネレーター」を Cloud Foundry 上で動かしてみたいと思います。
「静的サイト」であれば,手元で生成して staticfile-buildpack を使えばそれで終わりなのですが,このシリーズでは生成も Cloud Foundry 上で行うという趣旨で, Jekyll, Hugo, Sphinx の3つを紹介していきます。
今回はまず,blog のツールとしても多く使われている Jekyll を取り上げます。
基本情報
-
Jekyll の公式サイト
https://jekyllrb.com/
(日本語版: http://jekyllrb-ja.github.io/) -
Jekyll のソースコード (今回の記事では直接扱いません)
https://github.com/jekyll/jekyll -
今回デプロイするサンプルのソースコード
https://github.com/nota-ja/cf-jekyll-example -
その他参考情報
- heroku-buildpack-ruby-jekyll
https://github.com/mattmanning/heroku-buildpack-ruby-jekyll
今回 Cloud Foundry へのデプロイに使った buildpack のベースです
- heroku-buildpack-ruby-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” を参考にセットアップを行ってデプロイを試してみましたが,問題なく動作しました。文末にそのコミットへのリンクも記載しているので,興味のある方は試してみてください。
今回使用したソフトウェア
- cf-release (v215)
https://github.com/cloudfoundry/cf-release/tree/v215
(commit hash: 5fa14702bca4d36d1fdc7241c63d0b3e40dcbe90) - bosh-lite
https://github.com/cloudfoundry/bosh-lite/tree/1e82360f0bd00f75a367ddea81a024aebf514a74 - CF CLI (6.11.3-cebadc9-2015-05-20T19:00:58+00:00)
https://github.com/cloudfoundry/cli/releases/tag/v6.11.3
(commit hash: cebadc9e63f0cd17457539ac665878ec5cdc4eb0) - Jekyll gem v2.5.3
- heroku-buildpack-ruby-jekyll
https://github.com/nota-ja/heroku-buildpack-ruby-jekyll/tree/update
(commit hash: dc2014038dc74f834966b7a53556fcf33293b47f) - heroku-buildpack-multi
https://github.com/ddollar/heroku-buildpack-multi/tree/c41ef671cc9c8ff7d5cc7ad412654fbf9cffbce5 - cf-jekyll-example (本記事で使用したサンプル・サイト)
https://github.com/nota-ja/cf-jekyll-example/tree/d7a596c98a6fb516d366b2f6d8020d220e694139- 本記事で紹介した設定を追加したもの
https://github.com/nota-ja/cf-jekyll-example/tree/cf-100-day-challenge-087
(commit hash: aa3d82ab37b7e6e4f73af0338c89450bb979c152) - 単一 buildpack で動作する設定を追加したもの
https://github.com/nota-ja/cf-jekyll-example/tree/cf-100-day-challenge-087-single-buildpack
(commit hash: 88453f2a38fd7e418f72605b72e1f875607a88f3)
- 本記事で紹介した設定を追加したもの