Bluemix CFランタイムでPHPの掲示板を動作させたメモ


CFランタイムで、PHPを動作させようとすると、意外と難しいことが判った!? その理由も含めて忘れない様にメモです。 しかし、CloudFoundry のビルドパックの最新版が、Bluemix でも動作する事が確認できる成果がありました。


## 最小のPHPアプリのCFコンテナ起動

最も簡単で、PHPの実行環境を把握できるアプリを実行したいと思います。 ディレクトリを作成して、index.php を次の要領で作成します。

~~~
mac:bluemix maho$ mkdir tkr-php
imac:bluemix maho$ cd tkr-php/
imac:tkr-php maho$ cat << EOF > index.php
> <?php
>   phpinfo();
> ?>
> EOF
~~~

manifest.yml も何も作成していませんが、これで Bluemixへ プッシュすることで、インターネットからHTTPSでアクセスできるアプリが稼働します。 

~~~
imac:takara-php maho$ bx cf push tkr-php
~~~

これで、https://tkr-php.mybluemix.net/ をアクセスすると、次の画面が表示されます。 


![スクリーンショット 2017-07-19 11.23.52.png](https://qiita-image-store.s3.amazonaws.com/0/42829/32bdfe9a-76d1-ec8f-aa65-e7c7eab653df.png "スクリーンショット 2017-07-19 11.23.52.png")

しかし、PHP Version 5.5.38 と結構古いですね。 少なくとも、5.6 の最終版を利用したいところです。 これの理由は、Bluemix の PHPのビルドパックが古く更新されていないためです。 


## CloudFoundryの最新ビルドパックをBluemixで利用

そこで、PHP 5.6の最終版を利用するには、次の様に、Cloud Foundry の ビルドパックを指定することで、最新版を利用できます。

~~~
bx cf push -m 128M -b https://github.com/cloudfoundry/php-buildpack.git tkr-php
~~~

また、特定バージョンを使いたい場合は、次の様にビルドパックのバージョンを指定することもできます。 URLの後に、#v4.3.37 をおいて指定します。

~~~
bx cf push -m 128M -b https://github.com/cloudfoundry/php-buildpack.git#v4.3.37 tkr-php
~~~

このPHPのビルドパックの各バージョンとリリースノートは、https://github.com/cloudfoundry/php-buildpack/releases に公開されています。

前述の方法で、Cloud Foundry 提供の最新版のビルドパックで起動した場合、最新バージョンのPHP v5.6.31の実行環境が起動しています。

![スクリーンショット 2017-07-19 14.24.16.png](https://qiita-image-store.s3.amazonaws.com/0/42829/834f54de-bdb5-d70d-ba03-62d054c5b70e.png "スクリーンショット 2017-07-19 14.24.16.png")

PHPで日本語を利用する場合、CloudFoundry から提供されているビルドパックでは、日本語コードを扱うための[マルチバイト文字列](http://php.net/manual/ja/book.mbstring.php )(4)についての設定がされていません。PHPの日本語を処理の設定を追加したカスタムのビルドパックを作成する方法について後述します。

## ちょっと脇道
日本語環境を設定する前に、いろいろ知りたいことを探検します。

#### cfコマンドのオプションの調べ方

bx cf push の -m や -b のオプションは、役割の調べ方は、次の様にします。

~~~
imac:tkr-php maho$ bx cf push -h
'cf help push' を起動しています...

名前:
   push - 新しいアプリをプッシュしたり、既存のアプリに対して変更を同期します

使用法:
   Push a single app (with or without a manifest):
   cf push APP_NAME [-b BUILDPACK_NAME] [-c COMMAND] [-d DOMAIN] [-f MANIFEST_PATH] [--docker-image DOCKER_IMAGE]
   [-i NUM_INSTANCES] [-k DISK] [-m MEMORY] [--hostname HOST] [-p PATH] [-s STACK] [-t TIMEOUT] [-u (process | port | http)] [--route-path ROUTE_PATH]
   [--no-hostname] [--no-manifest] [--no-route] [--no-start] [--random-route]

   Push multiple apps with a manifest:
   cf push [-f MANIFEST_PATH]

別名:
   p

オプション:
   -b  名前 (例: my-buildpack) または Git URL (例: 'https://github.com/cloudfoundry/java-buildpack.git') またはブランチまたはタグ付きの Git URL (例:  'v3.3.0' タグの場合は 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0') によるカスタム・ビルドパック。 組み込みビルドパックのみを使用するには、'default' または 'null' を指定します
~~~





#### CFコンテナ内のプロセス


PHPやウェブサーバーが、どの様に実行されているか、確認するために、CFコンテナへログインして、状態を見ていきます。 コンテナへログインするには、次のコマンドを利用します。 ssh でログインするにあたり、Bluemix CLIのログインが出来ていれば、ssh でログインに際して認証は必要あリません。 vcap@から始まるプロンプトが出れば成功です。

~~~
$ bx cf ssh tkr-php
'cf ssh tkr-php' を起動しています...

vcap@5aaba83e-cffc-47bf-7fe1-a147:~$ 
~~~

CFコンテナで、psコマンドを実行すれば、何が動作しているか、見ることができます。 このプロセスのリストから、OS起動時のinitから、以下の２系統のプロセスが起動されていることがわかります。

~~~
vcap@5aaba83e-cffc-47bf-7fe1-a147:~$ ps exf
    PID TTY      STAT   TIME COMMAND
     14 ?        S<sl   0:33 python /home/vcap/app/.bp/bin/start CF_INSTANCE_ADDR=184.172.114.1
     34 ?        S<     0:00  \_ /bin/sh -c $HOME/httpd/bin/apachectl -f "$HOME/httpd/conf/http
     35 ?        S<     0:00  |   \_ /bin/sh /home/vcap/app/httpd/bin/apachectl -f /home/vcap/a
     38 ?        S<     0:00  |       \_ /app/httpd/bin/httpd -f /home/vcap/app/httpd/conf/http
     44 ?        S<     0:00  |           \_ /usr/bin/tee USER=vcap CF_INSTANCE_INTERNAL_IP=10.
     47 ?        S<     0:00  |           \_ /usr/bin/tee USER=vcap CF_INSTANCE_INTERNAL_IP=10.
     48 ?        S<l    0:02  |           \_ /app/httpd/bin/httpd -f /home/vcap/app/httpd/conf/
     49 ?        S<l    0:02  |           \_ /app/httpd/bin/httpd -f /home/vcap/app/httpd/conf/
     50 ?        S<l    0:02  |           \_ /app/httpd/bin/httpd -f /home/vcap/app/httpd/conf/
    143 ?        S<l    0:02  |           \_ /app/httpd/bin/httpd -f /home/vcap/app/httpd/conf/
     36 ?        S<     0:00  \_ /bin/sh -c $HOME/php/sbin/php-fpm -p "$HOME/php/etc" -y "$HOME
     40 ?        S<s    0:00      \_ php-fpm: master process (/home/vcap/app/php/etc/php-fpm.co
     45 ?        S<     0:00          \_ php-fpm: pool www                                     
     46 ?        S<     0:00          \_ php-fpm: pool www                                     
      8 ?        S<sl   0:00 /tmp/lifecycle/diego-sshd --allowedKeyExchanges= --address=0.0.0.0
   3653 pts/0    S<s    0:00  \_ /bin/bash PATH=/bin:/usr/bin LANG=en_US.UTF8 VCAP_SERVICES={}
   3831 pts/0    R<+    0:00      \_ ps exf CF_INSTANCE_ADDR=184.172.114.176:63518 BLUEMIX_REGI
~~~
PID 8 は、ログインするためのdiego-sshd で、Diegoコンテナ用に書かれたsshdです。(2) そして、PID 14 は、アプリのプロセスをスタートさせる Python のコードです。

この PID 14 から Apache httpd と php-fpm であることがわかります。 このプロセス FPM (FastCGI Process Manager) は PHP の FastCGI 実装のひとつで、 主に高負荷のサイトで有用な追加機能を用意しています。 (3)

あと残りの殆どのプロセスは、上記のPID 34,PID 36 の子プロセスである事が判ります。 この動作は、bx cf push する時に、適用されるビルドパックに仕込まれた仕掛けにより、この様な動きをしています。


#### ビルドパック (Buildpack)

このPHPのビルドパックのリリースノートは、https://github.com/cloudfoundry/php-buildpack/releases に公開されています。 このページによると、2017年7月19日現在では、v4.3.38 が最新バージョンで、PHP v5.6.31 のバイナリは、次のモジュールが組み込まれている事が解ります。mysql, redis, mongodb, memcached など、主要なミドルウェアが利用できる様になっている事が解ります。

![スクリーンショット 2017-07-19 7.56.58.png](https://qiita-image-store.s3.amazonaws.com/0/42829/9f4e524c-7f75-1adc-f5d8-7ae2edeb29a4.png "スクリーンショット 2017-07-19 7.56.58.png")


それから、次のソフトウェアもバンドルされています。  newrelic で監視できる様になっているんですね。

![スクリーンショット 2017-07-19 8.02.06.png](https://qiita-image-store.s3.amazonaws.com/0/42829/15735dfe-c7ac-10ab-5b37-a0f388b1b935.png "スクリーンショット 2017-07-19 8.02.06.png")


#### ビルドパックの動作

CloudFoundry のドキュメント(1)によれば、bc cf push した後の動作は、次の様なものだそうです。

* php アプリケーションの検知
* ビルドパックの実行
  * アプリケーションファイルのhtdocsへのコピー
* Apache HTTPD と PHP のダウンロード、ビルドパックの default にある内容で設定、そして、起動
* デフォルトのルート（URLのこと）でアクセスできる様になる



## 日本語環境の整備

本題に戻って、これから、CloudFoundry のビルドパックを元に、日本語処理環境を追加して、日本語の掲示板アプリが動作する様にしていきます。

#### GitHub Bluildpack のフォーク

GitHubにログインしておき、https://github.com/cloudfoundry/php-buildpack をアクセして、fork して、自分のリポジトリに複製を作ります。

![スクリーンショット 2017-07-19 22.00.12.png](https://qiita-image-store.s3.amazonaws.com/0/42829/e1f8232a-fd20-00db-e772-ce8953905d60.png "スクリーンショット 2017-07-19 22.00.12.png")

forkしたphp-buildpackをクローンして、編集して、カスタム・ビルドパックを作成していきます。

~~~
git clone https://github.com/takara9/php-buildpack fork-php-buildpack
~~~

マルチバイト文字列を扱うためのPHP機能拡張モジュール mbstring を default/optopns.json に追加します。

~~~file:default/options.json
{
    "STACK": "trusty",
    "LIBDIR": "lib",
    "WEBDIR": "htdocs",
    "WEB_SERVER": "httpd",
    "PHP_VM": "php",
    "ADMIN_EMAIL": "admin@localhost",
    "HTTPD_STRIP": true,
    "HTTPD_MODULES_STRIP": true,
    "NGINX_STRIP": true,
    "PHP_56_LATEST": "5.6.31",
    "PHP_70_LATEST": "7.0.21",
    "PHP_71_LATEST": "7.1.7",
    "PHP_STRIP": true,
    "PHP_MODULES_STRIP": true,
    "PHP_MODULES": [],
    "PHP_EXTENSIONS": ["bz2", "zlib", "curl", "mcrypt", "mbstring"],  <-- ここ
    "ZEND_EXTENSIONS": []
}
~~~


php.ini に mbstring(4)の設定を追加します。 php.ini のオプションの解説は、参考資料(5)にあります。解説を読んで設定するのは、辛いので、参考資料(6)を参照して mbstring の設定をおこないます。

~~~file:defaults/config/php/5.6.x/php.ini
    default_charset = "UTF-8"
    mbstring.language = Japanese
    mbstring.internal_encoding = UTF-8
    mbstring.encoding_translation = Off
    mbstring.http_input = pass
    mbstring.http_output = pass
    mbstring.detect_order = auto
~~~
それ以外の設定項目は、必要に応じて適宜実施します。


php.iniの編集が終わったら、GitHubに変更を反映します。

~~~
imac:fork-php-buildpack maho$ git add defaults
imac:fork-php-buildpack maho$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   defaults/config/php/5.6.x/php.ini
	modified:   defaults/options.json

imac:fork-php-buildpack maho$ git commit -m "for mbstring"
[master d80b838] for mbstring
 2 files changed, 6 insertions(+), 6 deletions(-)
imac:fork-php-buildpack maho$ git push
~~~

これで、日本語処理対応のカスタム・ビルドパックの作成は完了です。


### 掲示板ソフトのCFランタイム実行

インターネットを検索して見つけた、MySQLを使わないシンプルな掲示板ソフトを動かしてみます。 ファーストステップさんが公開している [シンプルなBBSの無料ダウンロード](https://www.1-firststep.com/archives/407) (7)を Bluemix 上で動作させます。

このサイトのガイドに従って、config.php を編集します。 そして、htdocsに index.php と common を置きます。
この時に利用するURLは、アプリ名を tkr-php としたら、 https://tkr-php.mybluemix.net となります。

下記の要領で、デプロイを実行します。

~~~
imac:tkr-php maho$ pwd
/Users/maho/bluemix/tkr-php
imac:tkr-php maho$ bx cf push -m 128M -b https://github.com/takara9/php-buildpack tkr-php
~~~

デプロイが完了したら、https://tkr-php.mybluemix.net へアクセスして、動作を確認します。 次の様な画面が表示されたら成功です。

![スクリーンショット 2017-07-19 22.57.25.png](https://qiita-image-store.s3.amazonaws.com/0/42829/f9d6d8c6-aeff-edf8-f61b-0d2740952666.png "スクリーンショット 2017-07-19 22.57.25.png")


# 感想

Bluemixが、威力を発揮する分野は、PHPで書かれたエコ・システムと思うんですが、ほとんど情報が無くいけないと思う次第です。 どうも注目を引く話題に流れる傾向があって、PHPのニーズ規模を見て欲しいですね。



# 参考資料

(1) Cloud Foundry Documentation PHP Buildpack https://docs.cloudfoundry.org/buildpacks/php/
(2) cloudfoundry/diego-ssh https://github.com/cloudfoundry/diego-ssh
(3) PHP Documentaion FastCGI Process Manager (FPM) http://php.net/manual/ja/install.fpm.php
(4) マルチバイト文字列 http://php.net/manual/ja/book.mbstring.php 
(5) 実行時設定 php.ini mbstring 設定オプション http://php.net/manual/ja/mbstring.configuration.php
(6) PHPをインストールしたらやっておきたい設定 http://qiita.com/knife0125/items/0e1af52255e9879f9332
(7) シンプルなBBSの無料ダウンロード https://www.1-firststep.com/archives/407