--- title: Paketo BuildpackでPHPアプリのDockerイメージを作成する tags: ["Cloud Native Buildpacks", "Paketo", "PHP"] categories: ["Dev", "Infrastructure", "CloudNativeBuildpacks", "Paketo"] date: 2021-09-04T17:10:34Z updated: 2021-09-05T02:31:34Z --- Paketo BuildpacksでPHPのコンテナイメージを作成するメモ。使用する [pack](https://github.com/buildpacks/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 < hello-php/htdocs/index.php 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 < 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 < 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): -> "" Selected Apache HTTP Server version (using ): 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のカスタマイズ例はこちら https://github.com/paketo-buildpacks/php-web/tree/main/integration/testdata/simple_app_custom_httpd_cfg #### WebサーバーをNginxに変更する Webサーバーを組み込みサーバーからNginxに変更したい場合も`buildpack.yml`に指定すれば良いです。 ``` cat < 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): -> "*" Selected Nginx Server version (using ): 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のカスタマイズ例はこちら https://github.com/paketo-buildpacks/php-web/tree/main/integration/testdata/simple_app_nginx_custom_cfg ### 拡張モジュールを追加する デフォルトで有効になっていない拡張モジュールを追加する例としてRedisを使用します。 ``` mkdir -p hello-redis/htdocs cat <<'EOF' > hello-redis/htdocs/index.php 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 < 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 < 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 < 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): -> "" -> "" 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 ``` アクセスします。 ![image](https://user-images.githubusercontent.com/106908/132102573-05a343a7-745e-4e9a-afb9-ca56b8a6ea23.png) ``` Call to undefined function Illuminate\Encryption\openssl_cipher_iv_length() ``` というエラーが出ました。opensslモジュールがロードされていないようです。 `extension.ini `ファイルを作成します。 ``` mkdir hello-laravel/.php.ini.d cat < 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 < 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 ``` アクセスします。 ![image](https://user-images.githubusercontent.com/106908/132102816-ba537b43-e70f-4d4a-a417-f55a0c674b16.png) 今度はアクセスできました。 --- PHPのことは詳しくないですが、Cloud Native Buildpacksを使ってソースコードからコンテナイメージが作成できました。 PHPやNginx, Apache HTTP Serverの設定やバージョンアップをBuildpack側に任せられて楽です。