hnwの日記

HerokuのBuildpackを利用してmbstringが有効なPHPサーバを立ててみた

HerokuといえばRubyのPaaSという印象が強いのは僕だけでしょうか。しかし、Herokuの現在の最新環境であるCedarでは下記の7つのプラットフォームをサポートしているんだそうです。(出典:The Celadon Cedar Stack | Heroku Dev Center


このうちFacebookだけが異彩を放っているんですが、説明を読んでみるとFacebookアプリに特化したもののようで、バックエンドの言語としてはRuby, Node.js, Python, PHPが使えるらしいです。(出典:Getting Started with Your Facebook App on Heroku | Heroku Dev Center)


PHPサポートしていないと見せかけてPHP使えるのか!やったぜ!と思いきや、現在デフォルトで提供されるPHPにはmbstringが入っていません。ションボリですね。


でも、あきらめることはありません。herokuのBuildpackという仕組みを使えばmbstringつきのPHPが簡単に手に入ります。

Buildpackとは

Buildpackというのは、アプリケーションをデプロイするたびに任意のコマンドを実行できる仕組みです。これを利用すれば、公式サポートされていない言語でもHeroku上で動作させることができます。


実際、第三者が作ったBuildpackの一覧を見ると、Emacs LispでWebアプリケーションを書きたいド変態向けのBuildpackが見つかったりします。世界は広いですね。


それはさておき、PHPのBuildpackは下記URLのようです(公式アナウンスは見つかりませんでしたが…)。


これ自体は現時点でmbstringをサポートしていないのですが、これに対してPull Requestを投げている人のmasterブランチではmbstringが有効になっていたので、今回はこれを使ってみました。


では実際に動かしてみましょう。

Herokuを使う準備

Herokuのアカウントを作り、herokuコマンドを有効にして「heroku login」するまでのところは説明を省略します。たとえば下記ページなどを参考にしてください。


僕はToolbeltをインストールせずにgem install herokuしてしまいましたが、そのあたりは趣味の問題だと思います。

プロジェクトディレクトリ以下に実験用ファイルを作る

まず、my-first-heroku-phpという名前でプロジェクトディレクトリを作ります。

$ mkdir $HOME/work/my-first-heroku-php/
$ cd $HOME/work/my-first-heroku-php/


次にindex.phpを作ります。phpinfoするだけです。

<?php phpinfo();


ひとまず完成!

デプロイ

gitのローカルリポジトリにcommitします。

$ git init
$ git add .
$ git commit -m "init"
[master (root-commit) 5e173fd] init
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 index.php
$


次にアプリケーションを作成します。ポイントは、ここで先ほどのBuildpackのURLを指定することです。

$ heroku create --buildpack https://github.com/winglian/heroku-buildpack-php -s cedar
Creating blazing-robot-2045... done, stack is cedar
BUILDPACK_URL=https://github.com/winglian/heroku-buildpack-php
http://blazing-robot-2045.herokuapp.com/ | git@heroku.com:blazing-robot-2045.git
Git remote heroku added
 !    Notice: on Wed, 20 June, our default stack will change to Cedar. http://bit.ly/Lh0rM5
$


アプリケーションができたのでデプロイします。

$ git push heroku master
Counting objects: 3, done.
Writing objects: 100% (3/3), 223 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Fetching custom buildpack... done
-----> PHP app detected
-----> Bundling Apache version 2.2.22
-----> Bundling PHP version 5.3.10
Creating Slug Identifier file with id: 430a6435d09ef45f94e54b22806dbfaa
-----> Discovering process types
       Procfile declares types -> (none)
       Default types for PHP   -> web
-----> Compiled slug size is 11.5MB
-----> Launching... done, v4
       http://blazing-robot-2045.herokuapp.com deployed to Heroku

To git@heroku.com:blazing-robot-2045.git
 * [new branch]      master -> master
$


おまじないとしてWebのプロセスを減らさないといけないらしいので、そのようにします。(このあたりは僕の理解が浅いです…)

$ heroku ps:scale web=1
Scaling web processes... done, now running 1
$


「heroku ps」コマンドで様子を見ます。

$ heroku ps
=== web: `sh boot.sh`
web.1: up for 6s
$


「heroku logs」コマンドで様子を見ます。

$ heroku logs
(略)
$


動いてそうな雰囲気なので、ブラウザで見てみましょう。下記コマンドでブラウザが開くと思います。

$ heroku open


やった!見慣れたphpinfoが表示されました。mbstringも有効になっています。

Buildpackの可能性

上記の手順を実際にやってみると、あまりの簡単さに驚くと思います。これでも他の環境に比べるとpush時の待ち時間が長い印象ですが、それでも20秒くらいで独自環境へのデプロイと再起動をしているわけですから、十分実用的です。


このBuildpackが誰でも作れるというのは、2つの意味で衝撃的だと感じます。1つめは、環境構築やパラメータチューニングと言った作業が今まで以上にオープンな作業になるということです。これまでも書籍やブログ・勉強会などを通じて情報交換が行われてきたとは思いますが、伝播の速度や伝わる人数には限界があったように思います。これがGitHub上のコミュニケーションで加速するとしたら、ちょっとワクワクしますね。


また、誰もが様々な環境を気軽に試せる点も面白いと思います。たとえばPHPに関して言えば、現時点ではApache+mod_php環境で利用している人が大多数でしょうけど、nginx+php-fpmのBuildpackがあったら試したい人は多いのではないでしょうか。実は僕も試したいくらいです。