Paketo BuildpacksでPHPのコンテナイメージを作成するメモ。使用する pack CLIのバージョンは次の通りです。
$ pack version
0.20.0+git-66a4f32.build-2668
参考にしたドキュメントは次の通りです。
- https://paketo.io/docs/howto/php
- https://github.com/paketo-buildpacks/samples/tree/main/php
- https://github.com/paketo-buildpacks/php-web/tree/main/integration/testdata
- https://github.com/paketo-buildpacks/php-composer/tree/main/integration/testdata
- https://github.com/paketo-buildpacks/php/tree/main/integration/testdata
目次
Hello World
まずは一番簡単なPHPアプリを作成。
Paketo Buildpackではデフォルトでhtdocsが公開ディレクトリ。
mkdir -p hello-php/htdocs
cat <<EOF > hello-php/htdocs/index.php
<?php echo 'Hello World! (PHP ' . phpversion() . ')';
EOF
使用するBuilderはpaketobuildpacks/builder:full。次のコマンドでイメージを作成します。
pack build ghcr.io/making/hello-php --builder paketobuildpacks/builder:full --path hello-php
ビルドログは次の通り。
full: Pulling from paketobuildpacks/builder
Digest: sha256:5815bb199fb92e21bae058df56416ab6e2a0a85609865b85c0bcfa8cbc56625e
Status: Image is up to date for paketobuildpacks/builder:full
full-cnb: Pulling from paketobuildpacks/run
Digest: sha256:fac2ca83109101e0d1dd8c26707f5f58e05ccf52b2c42db95e25bda86b9887b2
Status: Image is up to date for paketobuildpacks/run:full-cnb
===> DETECTING
Warning: Warning: buildpack paketo-buildpacks/php-web has a "version" key. This key is deprecated in build plan requirements in buildpack API 0.3. "metadata.version" should be used instead
3 of 9 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.0
paketo-buildpacks/php-dist 0.3.3
paketo-buildpacks/php-web 0.1.2
===> ANALYZING
Previous image with name "ghcr.io/making/hello-php" not found
===> RESTORING
===> BUILDING
Paketo CA Certificates Buildpack 2.4.0
https://github.com/paketo-buildpacks/ca-certificates
Launch Helper: Contributing to layer
Creating /layers/paketo-buildpacks_ca-certificates/helper/exec.d/ca-certificates-helper
Paketo PHP Distribution Buildpack 0.3.3
Resolving PHP version
Candidate version sources (in priority order):
default-versions -> "7.4.*"
Selected PHP version (using default-versions): 7.4.23
Executing build process
Installing PHP 7.4.23
Completed in 2.139s
Configuring environment
MIBDIRS -> "/layers/paketo-buildpacks_php-dist/php/mibs"
PATH -> "/layers/paketo-buildpacks_php-dist/php/sbin:$PATH"
PHP_API -> "20190902"
PHP_EXTENSION_DIR -> "/layers/paketo-buildpacks_php-dist/php/lib/php/extensions/no-debug-non-zts-20190902"
PHP_HOME -> "/layers/paketo-buildpacks_php-dist/php"
Paketo PHP Web Buildpack 0.1.2
PHP Web 6e8855d5fb50668eec565ef7b9f113b121b2a5597852389e434c9b9d18743739: Contributing to layer
Configuring PHP Application
Using feature -- PHP
Writing PHPRC to shared
Writing PHP_INI_SCAN_DIR to shared
Using feature -- PHP Web Server
Process types:
task: php -S 0.0.0.0:$PORT -t /workspace/htdocs
web: php -S 0.0.0.0:$PORT -t /workspace/htdocs
===> EXPORTING
Adding layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/php-dist:php'
Adding layer 'paketo-buildpacks/php-web:php-web'
Adding 1/1 app layer(s)
Adding layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving ghcr.io/making/hello-php...
*** Images (d3add6bf54df):
ghcr.io/making/hello-php
Adding cache layer 'paketo-buildpacks/php-dist:php'
Successfully built image ghcr.io/making/hello-php
作成したイメージを実行します。環境変数PORTでポートを指定しないといけないです。
$ docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-php
[Sat Sep 4 14:58:39 2021] PHP 7.4.23 Development Server (http://0.0.0.0:8080) started
組み込みサーバーが起動しました。アクセスしてみます。
$ curl http://localhost:8080
Hello World! (PHP 7.4.23)
サポートされるPHPのバージョンとデフォルトのバージョンはPHP Distribution Buildpackのバージョンに依存します。
今回はPHP Distribution Buildpack 0.3.3が使用されているので、このバージョンをリリースノート
https://github.com/paketo-buildpacks/php-dist/releases/tag/v0.3.3
を確認すると、デフォルトが7.4.*で、そのほか7.3.*と8.0.*の最新バージョンと一つ前のバージョンがサポートされていることがわかります。
PHPのバージョンを変更する
PHPのバージョンを指定したい場合は、buildpack.ymlにバージョンを指定します。PHP 8.0に変更してみます。
cat <<EOF > hello-php/buildpack.yml
---
php:
version: 8.0.*
EOF
再度ビルドします。
pack build ghcr.io/making/hello-php --builder paketobuildpacks/builder:full --path hello-php
ビルドログは次の通り。PHP 8.0がインストールされていることがわかります。
full: Pulling from paketobuildpacks/builder
Digest: sha256:5815bb199fb92e21bae058df56416ab6e2a0a85609865b85c0bcfa8cbc56625e
Status: Image is up to date for paketobuildpacks/builder:full
full-cnb: Pulling from paketobuildpacks/run
Digest: sha256:fac2ca83109101e0d1dd8c26707f5f58e05ccf52b2c42db95e25bda86b9887b2
Status: Image is up to date for paketobuildpacks/run:full-cnb
===> DETECTING
Warning: Warning: buildpack paketo-buildpacks/php-web has a "version" key. This key is deprecated in build plan requirements in buildpack API 0.3. "metadata.version" should be used instead
3 of 9 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.0
paketo-buildpacks/php-dist 0.3.3
paketo-buildpacks/php-web 0.1.2
===> ANALYZING
Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
Restoring metadata for "paketo-buildpacks/php-dist:php" from app image
Restoring metadata for "paketo-buildpacks/php-web:php-web" from app image
===> RESTORING
Restoring data for "paketo-buildpacks/php-dist:php" from cache
===> BUILDING
Paketo CA Certificates Buildpack 2.4.0
https://github.com/paketo-buildpacks/ca-certificates
Launch Helper: Reusing cached layer
Paketo PHP Distribution Buildpack 0.3.3
Resolving PHP version
Candidate version sources (in priority order):
buildpack.yml -> "8.0.*"
default-versions -> "7.4.*"
Selected PHP version (using buildpack.yml): 8.0.10
Executing build process
Installing PHP 8.0.10
Completed in 5.065s
Configuring environment
MIBDIRS -> "/layers/paketo-buildpacks_php-dist/php/mibs"
PATH -> "/layers/paketo-buildpacks_php-dist/php/sbin:$PATH"
PHP_API -> "20200930"
PHP_EXTENSION_DIR -> "/layers/paketo-buildpacks_php-dist/php/lib/php/extensions/no-debug-non-zts-20200930"
PHP_HOME -> "/layers/paketo-buildpacks_php-dist/php"
Paketo PHP Web Buildpack 0.1.2
PHP Web c49b83a4f6a804a8611e69ad754c76cf62cb509a4b546bbe6ed50c950ec52a61: Contributing to layer
Configuring PHP Application
Using feature -- PHP
Writing PHPRC to shared
Writing PHP_INI_SCAN_DIR to shared
Using feature -- PHP Web Server
Process types:
task: php -S 0.0.0.0:$PORT -t /workspace/htdocs
web: php -S 0.0.0.0:$PORT -t /workspace/htdocs
===> EXPORTING
Reusing layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/php-dist:php'
Adding layer 'paketo-buildpacks/php-web:php-web'
Adding 1/1 app layer(s)
Reusing layer 'launcher'
Adding layer 'config'
Reusing layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving ghcr.io/making/hello-php...
*** Images (74e4981ac54c):
ghcr.io/making/hello-php
Adding cache layer 'paketo-buildpacks/php-dist:php'
Successfully built image ghcr.io/making/hello-php
実行します。
$ docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-php
[Sat Sep 4 15:08:16 2021] PHP 8.0.10 Development Server (http://0.0.0.0:8080) started
組み込みサーバーが起動しました。アクセスしてみます。
$ curl http://localhost:8080
Hello World! (PHP 8.0.10)
WebサーバーをApache HTTP Serverに変更する
Webサーバーを組み込みサーバーからApache HTTP Serverに変更したい場合もbuildpack.ymlに指定すれば良いです。
cat <<EOF > hello-php/buildpack.yml
---
php:
webserver: httpd
EOF
再度ビルドします。
pack build ghcr.io/making/hello-php --builder paketobuildpacks/builder:full --path hello-php
ビルドログは次の通り。Apache HTTP Serverがインストールされていることがわかります。
full: Pulling from paketobuildpacks/builder
Digest: sha256:5815bb199fb92e21bae058df56416ab6e2a0a85609865b85c0bcfa8cbc56625e
Status: Image is up to date for paketobuildpacks/builder:full
full-cnb: Pulling from paketobuildpacks/run
Digest: sha256:fac2ca83109101e0d1dd8c26707f5f58e05ccf52b2c42db95e25bda86b9887b2
Status: Image is up to date for paketobuildpacks/run:full-cnb
===> DETECTING
Warning: Warning: buildpack paketo-buildpacks/php-web has a "version" key. This key is deprecated in build plan requirements in buildpack API 0.3. "metadata.version" should be used instead
4 of 9 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.0
paketo-buildpacks/httpd 0.1.1
paketo-buildpacks/php-dist 0.3.3
paketo-buildpacks/php-web 0.1.2
===> ANALYZING
Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
Restoring metadata for "paketo-buildpacks/php-dist:php" from app image
Restoring metadata for "paketo-buildpacks/php-web:php-web" from app image
===> RESTORING
Restoring data for "paketo-buildpacks/php-dist:php" from cache
===> BUILDING
Paketo CA Certificates Buildpack 2.4.0
https://github.com/paketo-buildpacks/ca-certificates
Launch Helper: Reusing cached layer
Paketo Apache HTTP Server Buildpack 0.1.1
Resolving Apache HTTP Server version
Candidate version sources (in priority order):
<unknown> -> ""
Selected Apache HTTP Server version (using <unknown>): 2.4.48
Executing build process
Installing Apache HTTP Server 2.4.48
Completed in 398ms
Configuring environment
APP_ROOT -> "/workspace"
SERVER_ROOT -> "/layers/paketo-buildpacks_httpd/httpd"
Paketo PHP Distribution Buildpack 0.3.3
Resolving PHP version
Candidate version sources (in priority order):
default-versions -> "7.4.*"
Selected PHP version (using default-versions): 7.4.23
Executing build process
Installing PHP 7.4.23
Completed in 2.302s
Configuring environment
MIBDIRS -> "/layers/paketo-buildpacks_php-dist/php/mibs"
PATH -> "/layers/paketo-buildpacks_php-dist/php/sbin:$PATH"
PHP_API -> "20190902"
PHP_EXTENSION_DIR -> "/layers/paketo-buildpacks_php-dist/php/lib/php/extensions/no-debug-non-zts-20190902"
PHP_HOME -> "/layers/paketo-buildpacks_php-dist/php"
Paketo PHP Web Buildpack 0.1.2
PHP Web 760228aff8ac402e7946d261215b234fa88226d4a7c4dbca78642386368eb24f: Contributing to layer
Configuring PHP Application
Using feature -- PHP
Writing PHPRC to shared
Writing PHP_INI_SCAN_DIR to shared
Using feature -- Apache Web Server
Using feature -- PhpFpm
Using feature -- ProcMgr
Process types:
web: procmgr /layers/paketo-buildpacks_php-web/php-web/procs.yml
===> EXPORTING
Reusing layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/httpd:httpd'
Adding layer 'paketo-buildpacks/php-dist:php'
Adding layer 'paketo-buildpacks/php-web:php-web'
Adding 1/1 app layer(s)
Reusing layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving ghcr.io/making/hello-php...
*** Images (0899054ad05f):
ghcr.io/making/hello-php
Adding cache layer 'paketo-buildpacks/php-dist:php'
Successfully built image ghcr.io/making/hello-php
実行します。
$ docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-php
[04-Sep-2021 15:14:17] NOTICE: fpm is running, pid 23
[04-Sep-2021 15:14:17] NOTICE: ready to handle connections
[Sat Sep 04 15:14:17.224008 2021] [mpm_event:notice] [pid 24:tid 139634204366720] AH00489: Apache/2.4.48 (Unix) configured -- resuming normal operations
[Sat Sep 04 15:14:17.224099 2021] [mpm_event:info] [pid 24:tid 139634204366720] AH00490: Server built: Jun 2 2021 01:19:36
[Sat Sep 04 15:14:17.224132 2021] [core:notice] [pid 24:tid 139634204366720] AH00094: Command line: 'httpd -f /workspace/httpd.conf -D FOREGROUND'
Apache HTTP Serverが起動しました。アクセスしてみます。
$ curl http://localhost:8080
Hello World! (PHP 7.4.23)
HTTPDのカスタマイズ例はこちら
WebサーバーをNginxに変更する
Webサーバーを組み込みサーバーからNginxに変更したい場合もbuildpack.ymlに指定すれば良いです。
cat <<EOF > hello-php/buildpack.yml
---
php:
webserver: nginx
EOF
再度ビルドします。
pack build ghcr.io/making/hello-php --builder paketobuildpacks/builder:full --path hello-php
ビルドログは次の通り。Nginxがインストールされていることがわかります。
full: Pulling from paketobuildpacks/builder
Digest: sha256:5815bb199fb92e21bae058df56416ab6e2a0a85609865b85c0bcfa8cbc56625e
Status: Image is up to date for paketobuildpacks/builder:full
full-cnb: Pulling from paketobuildpacks/run
Digest: sha256:fac2ca83109101e0d1dd8c26707f5f58e05ccf52b2c42db95e25bda86b9887b2
Status: Image is up to date for paketobuildpacks/run:full-cnb
===> DETECTING
Warning: Warning: buildpack paketo-buildpacks/php-web has a "version" key. This key is deprecated in build plan requirements in buildpack API 0.3. "metadata.version" should be used instead
4 of 9 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.0
paketo-buildpacks/nginx 0.3.2
paketo-buildpacks/php-dist 0.3.3
paketo-buildpacks/php-web 0.1.2
===> ANALYZING
Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
Restoring metadata for "paketo-buildpacks/php-dist:php" from app image
Restoring metadata for "paketo-buildpacks/php-web:php-web" from app image
===> RESTORING
Restoring data for "paketo-buildpacks/php-dist:php" from cache
===> BUILDING
Paketo CA Certificates Buildpack 2.4.0
https://github.com/paketo-buildpacks/ca-certificates
Launch Helper: Reusing cached layer
Paketo Nginx Server Buildpack 0.3.2
Resolving Nginx Server version
Candidate version sources (in priority order):
<unknown> -> "*"
Selected Nginx Server version (using <unknown>): 1.21.1
Executing build process
Installing Nginx Server 1.21.1
Completed in 800ms
Configuring environment
PATH -> "$PATH:/layers/paketo-buildpacks_nginx/nginx/sbin"
Writing profile.d/configure.sh
Calls executable that parses templates in nginx conf
Paketo PHP Distribution Buildpack 0.3.3
Resolving PHP version
Candidate version sources (in priority order):
default-versions -> "7.4.*"
Selected PHP version (using default-versions): 7.4.23
Reusing cached layer /layers/paketo-buildpacks_php-dist/php
Paketo PHP Web Buildpack 0.1.2
PHP Web 41eacd0c9c1e4af1d92dde54e79a5ea4d0c0e8daca9baf6c8fe74ac30c0875e9: Contributing to layer
Configuring PHP Application
Using feature -- PHP
Writing PHPRC to shared
Writing PHP_INI_SCAN_DIR to shared
Using feature -- Nginx
Using feature -- PhpFpm
Using feature -- ProcMgr
Process types:
web: procmgr /layers/paketo-buildpacks_php-web/php-web/procs.yml
===> EXPORTING
Reusing layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/nginx:nginx'
Reusing layer 'paketo-buildpacks/php-dist:php'
Adding layer 'paketo-buildpacks/php-web:php-web'
Adding 1/1 app layer(s)
Reusing layer 'launcher'
Adding layer 'config'
Reusing layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving ghcr.io/making/hello-php...
*** Images (8e07ef90b035):
ghcr.io/making/hello-php
Reusing cache layer 'paketo-buildpacks/php-dist:php'
Successfully built image ghcr.io/making/hello-php
実行します。
$ docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-php
2021/09/04 15:18:33 [notice] 29#0: using the "epoll" event method
2021/09/04 15:18:33 [notice] 29#0: nginx/1.21.1
2021/09/04 15:18:33 [notice] 29#0: built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
2021/09/04 15:18:33 [notice] 29#0: OS: Linux 5.10.25-linuxkit
2021/09/04 15:18:33 [notice] 29#0: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/09/04 15:18:33 [notice] 29#0: start worker processes
2021/09/04 15:18:33 [notice] 29#0: start worker process 31
2021/09/04 15:18:33 [notice] 29#0: start worker process 32
2021/09/04 15:18:33 [notice] 29#0: start worker process 33
2021/09/04 15:18:33 [notice] 29#0: start worker process 34
[04-Sep-2021 15:18:33] NOTICE: fpm is running, pid 30
[04-Sep-2021 15:18:33] NOTICE: ready to handle connections
Nginxが起動しました。アクセスしてみます。
$ curl http://localhost:8080
Hello World! (PHP 7.4.23)
Nginxのカスタマイズ例はこちら
拡張モジュールを追加する
デフォルトで有効になっていない拡張モジュールを追加する例としてRedisを使用します。
mkdir -p hello-redis/htdocs
cat <<'EOF' > hello-redis/htdocs/index.php
<?php
$redis = new Redis();
$redis->connect(getenv('REDIS_HOST'), getenv('REDIS_PORT'));
echo $redis->ping();
EOF
まずはそのままビルドします。
pack build ghcr.io/making/hello-redis --builder paketobuildpacks/builder:full --path hello-redis
実行します。この時点でエラーは出ません。
$ docker run --rm -e PORT=8080 -e REDIS_HOST=host.docker.internal -e REDIS_PORT=6379 -p 8080:8080 ghcr.io/making/hello-redis
[Sat Sep 4 16:16:06 2021] PHP 7.4.23 Development Server (http://0.0.0.0:8080) started
アクセスしてみます。
curl http://localhost:8080
サーバーで実行時エラーが出力されます。
[Sat Sep 4 16:18:26 2021] 172.17.0.1:64374 Accepted
[Sat Sep 4 16:18:26 2021] PHP Fatal error: Uncaught Error: Class 'Redis' not found in /workspace/htdocs/index.php:2
Stack trace:
#0 {main}
thrown in /workspace/htdocs/index.php on line 2
[Sat Sep 4 16:18:26 2021] 172.17.0.1:64374 [500]: GET / - Uncaught Error: Class 'Redis' not found in /workspace/htdocs/index.php:2
Stack trace:
#0 {main}
thrown in /workspace/htdocs/index.php on line 2
[Sat Sep 4 16:18:26 2021] 172.17.0.1:64374 Closing
lass 'Redis' not foundと言われているので拡張モジュールがロードされていません。
拡張モジュールを追加するには.php.dディレクトリを作成してその中に任意の.iniファイルを作成して.soファイルを記述すれば良いです。
mkdir hello-redis/.php.ini.d
cat <<EOF > hello-redis/.php.ini.d/extension.ini
extension=redis.so
EOF
再度ビルドします。
pack build ghcr.io/making/hello-redis --builder paketobuildpacks/builder:full --path hello-redis
実行します。
$ docker run --rm -e PORT=8080 -e REDIS_HOST=host.docker.internal -e REDIS_PORT=6379 -p 8080:8080 ghcr.io/making/hello-redis
[Sat Sep 4 16:23:01 2021] PHP Warning: Cannot load module 'redis' because required module 'igbinary' is not loaded in Unknown on line 0
[Sat Sep 4 16:23:01 2021] PHP 7.4.23 Development Server (http://0.0.0.0:8080) started
igbinaryモジュールがないからredisモジュールがロードできないというワーニングが出ているのでextension.iniを更新します。
cat <<EOF > hello-redis/.php.ini.d/extension.ini
extension=redis.so
extension=igbinary.so
EOF
再度ビルドします。
pack build ghcr.io/making/hello-redis --builder paketobuildpacks/builder:full --path hello-redis
実行します。
$ docker run --rm -e PORT=8080 -e REDIS_HOST=host.docker.internal -e REDIS_PORT=6379 -p 8080:8080 ghcr.io/making/hello-redis
[Sat Sep 4 16:25:49 2021] PHP 7.4.23 Development Server (http://0.0.0.0:8080) started
起動しました。アクセスします。
$ curl http://localhost:8080
1
レスポンスが無事返りました。
Laravelを使う
PHPのデファクトスタンダードなフレームワークであるLaravelで作られたアプリのコンテナイメージを作成します。
brew install composer
composer global require laravel/installer
export PATH=$HOME/.composer/vendor/bin:$PATH
laravel new hello-laravel --git
Composerが使われている場合、composer.jsonに設定されているPHPバージョンとの整合性チェックが行われます。
$ ls -l hello-laravel
total 600
-rw-r--r-- 1 toshiaki wheel 3964 Aug 25 00:59 README.md
drwxr-xr-x 7 toshiaki wheel 224 Aug 25 00:59 app
-rwxr-xr-x 1 toshiaki wheel 1686 Aug 25 00:59 artisan
drwxr-xr-x 4 toshiaki wheel 128 Aug 25 00:59 bootstrap
-rw-r--r-- 1 toshiaki wheel 1735 Aug 25 00:59 composer.json
-rw-r--r-- 1 toshiaki wheel 273409 Sep 5 01:35 composer.lock
drwxr-xr-x 17 toshiaki wheel 544 Aug 25 00:59 config
drwxr-xr-x 6 toshiaki wheel 192 Aug 25 00:59 database
-rw-r--r-- 1 toshiaki wheel 473 Aug 25 00:59 package.json
-rw-r--r-- 1 toshiaki wheel 1202 Aug 25 00:59 phpunit.xml
drwxr-xr-x 7 toshiaki wheel 224 Aug 25 00:59 public
drwxr-xr-x 6 toshiaki wheel 192 Aug 25 00:59 resources
drwxr-xr-x 6 toshiaki wheel 192 Aug 25 00:59 routes
-rw-r--r-- 1 toshiaki wheel 563 Aug 25 00:59 server.php
drwxr-xr-x 5 toshiaki wheel 160 Aug 25 00:59 storage
drwxr-xr-x 6 toshiaki wheel 192 Aug 25 00:59 tests
drwxr-xr-x 43 toshiaki wheel 1376 Sep 5 01:35 vendor
-rw-r--r-- 1 toshiaki wheel 559 Aug 25 00:59 webpack.mix.js
$ cat hello-laravel/composer.json | grep '"php"'
"php": "^7.3|^8.0",
今回の例では7.3か8.0のみサポートされており、Buildpackのデフォルトである7.4と合わないため、buildpack.ymlに使用するPHPのバージョンを明示します。
また生成された公開ディレクトリはpublicなので、これもbuildpack.yml
cat <<EOF > hello-laravel/buildpack.yml
---
php:
version: 7.3.*
webdirectory: public
EOF
ビルドします。package.jsonがあるため、そのまま実行するとNode.jsアプリと検出され、PHPのインストールが行われません。
Node.js BuildpackとPHP Buildpack両方が使用されるように--buildpackオプションを指定します。最後に指定したBuildpackが起動用に使用されます。
$ pack build ghcr.io/making/hello-laravel --builder paketobuildpacks/builder:full --path hello-laravel --buildpack paketo-buildpacks/nodejs --buildpack paketo-buildpacks/php
full: Pulling from paketobuildpacks/builder
Digest: sha256:5815bb199fb92e21bae058df56416ab6e2a0a85609865b85c0bcfa8cbc56625e
Status: Image is up to date for paketobuildpacks/builder:full
full-cnb: Pulling from paketobuildpacks/run
Digest: sha256:fac2ca83109101e0d1dd8c26707f5f58e05ccf52b2c42db95e25bda86b9887b2
Status: Image is up to date for paketobuildpacks/run:full-cnb
===> DETECTING
Warning: Warning: buildpack paketo-buildpacks/php-composer has a "version" key. This key is deprecated in build plan requirements in buildpack API 0.3. "metadata.version" should be used instead
Warning: Warning: buildpack paketo-buildpacks/php-web has a "version" key. This key is deprecated in build plan requirements in buildpack API 0.3. "metadata.version" should be used instead
8 of 14 buildpacks participating
paketo-buildpacks/ca-certificates 2.4.0
paketo-buildpacks/node-engine 0.7.1
paketo-buildpacks/npm-install 0.4.0
paketo-buildpacks/node-module-bom 0.1.1
paketo-buildpacks/npm-start 0.3.0
paketo-buildpacks/php-dist 0.3.3
paketo-buildpacks/php-composer 0.2.2
paketo-buildpacks/php-web 0.1.2
===> ANALYZING
Previous image with name "ghcr.io/making/hello-laravel" not found
Restoring metadata for "paketo-buildpacks/node-module-bom:cyclonedx-node-module" from cache
Restoring metadata for "paketo-buildpacks/php-composer:be95557cc36eeb82da0f4340a469bad56b57f742d2891892dcb2f8b0179790ec" from cache
Restoring metadata for "paketo-buildpacks/php-composer:php-composer-cache" from cache
===> RESTORING
Restoring data for "paketo-buildpacks/node-module-bom:cyclonedx-node-module" from cache
Restoring data for "paketo-buildpacks/php-composer:be95557cc36eeb82da0f4340a469bad56b57f742d2891892dcb2f8b0179790ec" from cache
Restoring data for "paketo-buildpacks/php-composer:php-composer-cache" from cache
===> BUILDING
Paketo CA Certificates Buildpack 2.4.0
https://github.com/paketo-buildpacks/ca-certificates
Launch Helper: Contributing to layer
Creating /layers/paketo-buildpacks_ca-certificates/helper/exec.d/ca-certificates-helper
Paketo Node Engine Buildpack 0.7.1
Resolving Node Engine version
Candidate version sources (in priority order):
-> ""
<unknown> -> ""
Selected Node Engine version (using ): 14.17.6
Executing build process
Installing Node Engine 14.17.6
Completed in 1.795s
Configuring build environment
NODE_ENV -> "production"
NODE_HOME -> "/layers/paketo-buildpacks_node-engine/node"
NODE_VERBOSE -> "false"
Configuring launch environment
NODE_ENV -> "production"
NODE_HOME -> "/layers/paketo-buildpacks_node-engine/node"
NODE_VERBOSE -> "false"
Writing profile.d/0_memory_available.sh
Calculates available memory based on container limits at launch time.
Made available in the MEMORY_AVAILABLE environment variable.
Paketo NPM Install Buildpack 0.4.0
Resolving installation process
Process inputs:
node_modules -> "Not found"
npm-cache -> "Not found"
package-lock.json -> "Not found"
Selected NPM build process: 'npm install'
Executing build process
Running 'npm install --unsafe-perm --cache /layers/paketo-buildpacks_npm-install/npm-cache'
Completed in 15.962s
Configuring launch environment
NPM_CONFIG_LOGLEVEL -> "error"
Configuring environment shared by build and launch
PATH -> "$PATH:/layers/paketo-buildpacks_npm-install/modules/node_modules/.bin"
Paketo Node Module Bill of Materials Generator Buildpack 0.1.1
Resolving CycloneDX Node.js Module version
Selected CycloneDX Node.js Module version: 3.0.6
Reusing cached layer /layers/paketo-buildpacks_node-module-bom/cyclonedx-node-module
Configuring environment
Appending CycloneDX Node.js Module onto PATH
Running CycloneDX Node.js Module
Running 'cyclonedx-bom -o bom.json'
Completed in 270ms
Paketo NPM Start Buildpack 0.3.0
Assigning launch processes
web: node server.js
Paketo PHP Distribution Buildpack 0.3.3
Resolving PHP version
Candidate version sources (in priority order):
buildpack.yml -> "7.3.*"
composer.lock -> "^7.3|^8.0"
default-versions -> "7.4.*"
Selected PHP version (using buildpack.yml): 7.3.30
Executing build process
Installing PHP 7.3.30
Completed in 3.007s
Configuring environment
MIBDIRS -> "/layers/paketo-buildpacks_php-dist/php/mibs"
PATH -> "/layers/paketo-buildpacks_php-dist/php/sbin:$PATH"
PHP_API -> "20180731"
PHP_EXTENSION_DIR -> "/layers/paketo-buildpacks_php-dist/php/lib/php/extensions/no-debug-non-zts-20180731"
PHP_HOME -> "/layers/paketo-buildpacks_php-dist/php"
Paketo PHP Composer Buildpack 0.2.2
2.1.5: Contributing to layer
Reusing cached download from previous build
Expanding to /layers/paketo-buildpacks_php-composer/composer
PHP Composer Cache 96ebbb5c8694dd2c33b07ca6d40c10b0b670bc10176d2507d8b3b4a739d46f01: Reusing cached layer
Checking platform requirements for packages in the vendor dir
PHP Composer 0a07c8a562dc6c59f9c2cba99152272526f688dd9bd63efeeabb62fe7569615b: Contributing to layer
Installing dependencies from lock file
Verifying lock file contents can be installed on current platform.
Package operations: 0 installs, 0 updates, 40 removals
- Removing theseer/tokenizer (1.2.1)
- Removing sebastian/version (3.0.2)
- Removing sebastian/type (2.3.4)
- Removing sebastian/resource-operations (3.0.3)
- Removing sebastian/recursion-context (4.0.4)
- Removing sebastian/object-reflector (2.0.4)
- Removing sebastian/object-enumerator (4.0.4)
- Removing sebastian/lines-of-code (1.0.3)
- Removing sebastian/global-state (5.0.3)
- Removing sebastian/exporter (4.0.3)
- Removing sebastian/environment (5.1.3)
- Removing sebastian/diff (4.0.4)
- Removing sebastian/complexity (2.0.2)
- Removing sebastian/comparator (4.0.6)
- Removing sebastian/code-unit-reverse-lookup (2.0.3)
- Removing sebastian/code-unit (1.0.8)
- Removing sebastian/cli-parser (1.0.1)
- Removing phpunit/phpunit (9.5.9)
- Removing phpunit/php-timer (5.0.3)
- Removing phpunit/php-text-template (2.0.4)
- Removing phpunit/php-invoker (3.1.1)
- Removing phpunit/php-file-iterator (3.0.5)
- Removing phpunit/php-code-coverage (9.2.6)
- Removing phpspec/prophecy (1.13.0)
- Removing phpdocumentor/type-resolver (1.4.0)
- Removing phpdocumentor/reflection-docblock (5.2.2)
- Removing phpdocumentor/reflection-common (2.2.0)
- Removing phar-io/version (3.1.0)
- Removing phar-io/manifest (2.0.3)
- Removing nunomaduro/collision (v5.9.0)
- Removing myclabs/deep-copy (1.10.2)
- Removing mockery/mockery (1.4.3)
- Removing laravel/sail (v1.10.1)
- Removing hamcrest/hamcrest-php (v2.0.1)
- Removing filp/whoops (2.14.1)
- Removing fakerphp/faker (v1.15.0)
- Removing facade/ignition-contracts (1.0.2)
- Removing facade/ignition (2.12.0)
- Removing facade/flare-client-php (1.8.1)
- Removing doctrine/instantiator (1.4.0)
Package sebastian/resource-operations is abandoned, you should avoid using it. No replacement was suggested.
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Package manifest generated successfully.
47 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
Paketo PHP Web Buildpack 0.1.2
PHP Web b684f3e8d951036f5c031a2d53ee2c672557a7f28f1129e6cb7afc90a71c05f0: Contributing to layer
Configuring PHP Application
Using feature -- PHP
Writing PHPRC to shared
Writing PHP_INI_SCAN_DIR to shared
Using feature -- PHP Web Server
Process types:
task: php -S 0.0.0.0:$PORT -t /workspace/public
web: php -S 0.0.0.0:$PORT -t /workspace/public
===> EXPORTING
Adding layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/node-engine:node'
Adding layer 'paketo-buildpacks/npm-install:modules'
Adding layer 'paketo-buildpacks/npm-install:npm-cache'
Adding layer 'paketo-buildpacks/php-dist:php'
Adding layer 'paketo-buildpacks/php-composer:php-composer-packages'
Adding layer 'paketo-buildpacks/php-web:php-web'
Adding 1/1 app layer(s)
Adding layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving ghcr.io/making/hello-laravel...
*** Images (2edef2f24d3d):
ghcr.io/making/hello-laravel
Reusing cache layer 'paketo-buildpacks/node-engine:node'
Reusing cache layer 'paketo-buildpacks/npm-install:modules'
Adding cache layer 'paketo-buildpacks/npm-install:npm-cache'
Reusing cache layer 'paketo-buildpacks/node-module-bom:cyclonedx-node-module'
Reusing cache layer 'paketo-buildpacks/php-dist:php'
Reusing cache layer 'paketo-buildpacks/php-composer:be95557cc36eeb82da0f4340a469bad56b57f742d2891892dcb2f8b0179790ec'
Reusing cache layer 'paketo-buildpacks/php-composer:php-composer-cache'
Successfully built image ghcr.io/making/hello-laravel
実行します。
docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-laravel
アクセスします。

Call to undefined function Illuminate\Encryption\openssl_cipher_iv_length()
というエラーが出ました。opensslモジュールがロードされていないようです。
extension.ini ファイルを作成します。
mkdir hello-laravel/.php.ini.d
cat <<EOF > hello-laravel/.php.ini.d/extension.ini
extension=openssl.so
EOF
関連issueがあるので、将来的にはこの設定は不要になるかもしれません。
https://github.com/paketo-buildpacks/php-composer/issues/190
再度ビルドします。
pack build ghcr.io/making/hello-laravel --builder paketobuildpacks/builder:full --path hello-laravel --buildpack paketo-buildpacks/nodejs --buildpack paketo-buildpacks/php
実行します。
docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-laravel
アクセスすると、今度は次のエラーが出力されます。
[Sat Sep 4 17:05:32 2021] PHP Warning: include(/layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/../../app/Http/Kernel.php): failed to open stream: No such file or directory in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/ClassLoader.php on line 480
[Sat Sep 4 17:05:32 2021] PHP Warning: include(): Failed opening '/layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/../../app/Http/Kernel.php' for inclusion (include_path='/layers/paketo-buildpacks_php-dist/php/lib/php:/workspace/lib') in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/composer/ClassLoader.php on line 480
[Sat Sep 4 17:05:32 2021] PHP Fatal error: Uncaught ReflectionException: Class App\Http\Kernel does not exist in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php:873
Stack trace:
#0 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(873): ReflectionClass->__construct('App\\Http\\Kernel')
#1 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(754): Illuminate\Container\Container->build('App\\Http\\Kernel')
#2 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(841): Illuminate\Container\Container->resolve('App\\Http\\Kernel', Array, false)
#3 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(294): Illuminate\Foundation\Application->resolve('App\\Http\\Kernel', Array, false)
#4 /layers/ in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 875
[Sat Sep 4 17:05:32 2021] 172.17.0.1:64658 [500]: / - Uncaught ReflectionException: Class App\Http\Kernel does not exist in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php:873
Stack trace:
#0 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(873): ReflectionClass->__construct('App\\Http\\Kernel')
#1 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(754): Illuminate\Container\Container->build('App\\Http\\Kernel')
#2 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(841): Illuminate\Container\Container->resolve('App\\Http\\Kernel', Array, false)
#3 /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php(294): Illuminate\Foundation\Application->resolve('App\\Http\\Kernel', Array, false)
#4 /layers/ in /layers/paketo-buildpacks_php-composer/php-composer-packages/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 875
https://github.com/paketo-buildpacks/php/issues/366 を見ると、コンテナイメージ内のフォルダ構造上、シンボリックリンクを作成しないといけないようです。
cat <<EOF > hello-laravel/.profile
#!/bin/bash
ln -s /workspace/app /layers/paketo-buildpacks_php-composer/php-composer-packages/app
EOF
再度ビルドします。
pack build ghcr.io/making/hello-laravel --builder paketobuildpacks/builder:full --path hello-laravel --buildpack paketo-buildpacks/nodejs --buildpack paketo-buildpacks/php
実行します。
docker run --rm -e PORT=8080 -p 8080:8080 ghcr.io/making/hello-laravel
アクセスします。

今度はアクセスできました。
PHPのことは詳しくないですが、Cloud Native Buildpacksを使ってソースコードからコンテナイメージが作成できました。
PHPやNginx, Apache HTTP Serverの設定やバージョンアップをBuildpack側に任せられて楽です。