Sunday, September 08, 2019

PHP Cloud Native Buildpacks Now in the Official Builder

In my previous post, I talked about how to use the PHP Cloud Native buildpacks. It was not super tricky but required some manual work to set up. This is because the PHP CNBs were not, at the time, part of an official builder.

What's a builder? It's basically an image containing a bunch of CNBs, all ready for your use. See this link for more details.

If you are to run `pack suggest-builders`, then you will see the list of official builders. At the time of writing, that is Heroku, Cloud Foundry (bionic) and Cloud Foundry (cflinuxfs3).

$ pack suggest-builders
Suggested builders:
    Heroku:            heroku/buildpacks:18            heroku-18 base image with buildpacks for Ruby, Java, Node.js, Python, Golang, & PHP
    Cloud Foundry:     cloudfoundry/cnb:bionic         Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang
    Cloud Foundry:     cloudfoundry/cnb:cflinuxfs3     cflinuxfs3 base image with buildpacks for Java, NodeJS, Python, Golang, PHP, HTTPD and NGINX

Tip: Learn more about a specific builder with:
    pack inspect-builder [builder image]

Notice how PHP is now included in the Cloud Foundry cflinuxfs3 builder.

So now, instead of all the work I had you doing in my last post, you can just run `pack build --builder "cloudfoundry/cnb:cflinuxfs3"`. The builder will automatically select the PHP CNBs, because it sees you're trying to build a PHP app. The result will be an image you can run with `docker run -it -e PORT=8080 -p 8080:8080 image-name`, just like in my previous post.

That's it! If you'd like to understand the output a bit more, keep reading. Otherwise go and enjoy!

If you're curious about the output, the interesting new bit is the DETECTING phase. In the previous post, we manually specified just the PHP CNBs, so that's all you'd see in the output. Now, we see many CNBs running, but only the PHP CNBs will be selected and actually run at build time.

[detector] ======== Results ========
[detector] skip: org.cloudfoundry.archiveexpanding@1.0.0-RC03
[detector] pass: org.cloudfoundry.openjdk@1.0.0-RC03
[detector] skip: org.cloudfoundry.buildsystem@1.0.0-RC03
[detector] pass: org.cloudfoundry.jvmapplication@1.0.0-RC03
[detector] pass: org.cloudfoundry.tomcat@1.0.0-RC03
[detector] pass: org.cloudfoundry.springboot@1.0.0-RC03
[detector] pass: org.cloudfoundry.distzip@1.0.0-RC03
[detector] skip: org.cloudfoundry.procfile@1.0.0-RC03
[detector] skip: org.cloudfoundry.azureapplicationinsights@1.0.0-RC03
[detector] skip: org.cloudfoundry.debug@1.0.0-RC03
[detector] skip: org.cloudfoundry.googlestackdriver@1.0.0-RC03
[detector] skip: org.cloudfoundry.jdbc@1.0.0-RC03
[detector] skip: org.cloudfoundry.jmx@1.0.0-RC03
[detector] pass: org.cloudfoundry.springautoreconfiguration@1.0.0-RC03
[detector] Resolving plan... (try #1)
[detector] fail: org.cloudfoundry.jvmapplication@1.0.0-RC03 requires jvm-application
[detector] Resolving plan... (try #2)
[detector] fail: org.cloudfoundry.jvmapplication@1.0.0-RC03 requires openjdk-jre
[detector] Resolving plan... (try #3)
[detector] fail: org.cloudfoundry.jvmapplication@1.0.0-RC03 requires jvm-application
[detector] ======== Output: org.cloudfoundry.yarn@0.0.24 ========
[detector] no "yarn.lock" found at: /workspace/yarn.lock
[detector] ======== Results ========
[detector] pass: org.cloudfoundry.node-engine@0.0.46
[detector] fail: org.cloudfoundry.yarn@0.0.24
[detector] ======== Results ========
[detector] pass: org.cloudfoundry.node-engine@0.0.46
[detector] fail: org.cloudfoundry.npm@0.0.29
[detector] ======== Output: org.cloudfoundry.pipenv@0.0.14 ========
[detector] no Pipfile found
[detector] ======== Results ========
[detector] pass: org.cloudfoundry.python@0.0.20
[detector] skip: org.cloudfoundry.pipenv@0.0.14
[detector] pass: org.cloudfoundry.pip@0.0.20
[detector] Resolving plan... (try #1)
[detector] fail: org.cloudfoundry.pip@0.0.20 requires requirements
[detector] ======== Results ========
[detector] fail: org.cloudfoundry.conda@0.0.13
[detector] ======== Output: org.cloudfoundry.dotnet-core-conf@0.0.20 ========
[detector] *.runtimeconfig.json file not found
[detector] ======== Results ========
[detector] fail: org.cloudfoundry.dotnet-core-conf@0.0.20
[detector] ======== Output: org.cloudfoundry.go-mod@0.0.18 ========
[detector] no "go.mod" found at: /workspace/go.mod
[detector] ======== Results ========
[detector] pass: org.cloudfoundry.go-compiler@0.0.20
[detector] fail: org.cloudfoundry.go-mod@0.0.18
[detector] ======== Output: org.cloudfoundry.dep@0.0.17 ========
[detector] failed detection: no Gopkg.toml found at root level
[detector] ======== Results ========
[detector] pass: org.cloudfoundry.go-compiler@0.0.20
[detector] fail: org.cloudfoundry.dep@0.0.17
[detector] ======== Output: org.cloudfoundry.php-composer@0.0.16 ========
[detector] no "composer.json" found in the following locations: [/workspace/composer.json /workspace/htdocs/composer.json]
[detector] ======== Results ========
[detector] pass: org.cloudfoundry.php-dist@0.0.28
[detector] skip: org.cloudfoundry.php-composer@0.0.16
[detector] pass: org.cloudfoundry.httpd@0.0.18
[detector] pass: org.cloudfoundry.php-web@0.0.18
[detector] Resolving plan... (try #1)
[detector] skip: org.cloudfoundry.httpd@0.0.18 provides unused httpd
[detector] Success! (2)

See how they all fail, until you get down to the PHP CNBs. Then you see Success!.

Then just like the last time, we see the PHP CNBs running during the BUILD phase.

[builder] PHP Buildpack 0.0.28
[builder]   PHP 7.2.22: Contributing to layer
[builder]     Downloading from
[builder]     Verifying checksum
[builder]        Expanding to /layers/org.cloudfoundry.php-dist/php-binary
[builder]     Writing PATH to shared
[builder]     Writing MIBDIRS to shared
[builder]     Writing PHP_HOME to shared
[builder]     Writing PHP_EXTENSION_DIR to shared
[builder]     Writing PHP_API to shared
[builder] PHP Web Buildpack 0.0.18
[builder]   Configuring PHP Script
[builder]   PHP Web 173b6da1f1b7b7a59af0c2ebcfe1c4ea4b183063a90b92f1f2ae6d8a9ebb0bfd: Contributing to layer
[builder]     Writing PHPRC to shared
[builder]     Writing PHP_INI_SCAN_DIR to shared
[builder] WARNING: `app.php` start script not found. App will not start unless you specify a custom start command.
[builder]   Process types:
[builder]     task: php /workspace/app.php
[builder]     web:  php /workspace/app.php

That's all there is too it.