Weekend tinkering: Building FrankenPHP Laravel binaries
For those who don't know of it, FrankenPHP is a great all-in-one tool for PHP apps: it contains a very fast PHP runner (fpm alternative, similar to Swoole & Roadrunner), as well as being bundled with the Caddy webserver, all in one binary file! It's a great example of the synergy between Golang and PHP.
I'm on an M1 mac, using Laravel Herd.
This post is a log of progress and issues I've had.
It's NOT an attempt to complain, but just show the process of figuring things out and learning.
The goals here are:
First challenge: Seems the default PHP extension list is small and you'll need to add your project's extensions to the static-build.Dockerfile.
No biggie, but I'd probably add a reminder in the docs to do this.
All I needed to add was pdo and sqlite.
I noticed that FrankenPHP builds use Alpine, because Alpine using musl libc results in smaller binary sizes.
This is in contrast to the creator's (great) article on PHP app containerisation tips which recommends against Alpine due to potential compatibility issues..
Lesson: There's always a good exception!
Recommended read: Containerisation for PHP apps
After that, the build started going...
and going...
and going...
Total build time: 81 minutes! Apparently this is due to upx, so another time I'll try without it and see how it goes. For prod deployments however it'd be more ideal to use it, but likely on a build server instead.
领英推荐
Next: macOS local build. I don't use Docker or a VM for my projects, so it'd be ideal to have a native build to run on my machine.
First issue: the build script is not finding the?hash?extension somehow, despite it being built-in to php since 7.4?
Since the host OS type builds rely on cloning FrankenPHP directly and running?the build script, we can luckily modify that file ??
The problem seems to be that calls passed to?static-php-cli?have the list of your project's extension dependencies passed through to it.
This can include core PHP extensions like?hash,?json,?pcre etc.?
static-php-cli does not like it when you pass builtins to its extension list for the?spc download?command. Laravel and other projects, especially if they've existed for many PHP versions, will be likely to include these extensions as dependencies, from when they were not included in the PHP core.
What I'm interested in is why this wasn't an issue in the Docker build? My dependencies are the same. Question for another time.
I hard coded the output of my project's extensions in the build script, sans the builtins (in my case hash, json, pcre) and it started going again. Onwards!
Next problem: Build is failing, because it seems to be looking for libraries in a nested way that is duplicating the path. E.g. `Users/nik/.../project/lib//Users/nik/project.../lib`.
Now I'm not clued up as to everything going on in this script, so I put the commands being run and my errors into Claude AI. It recommended removing a `sed` command in the CGO_CFLAGS parts of the script, which worked.
So the build started running! Didn't finish though.
Now, the error is `fatal error: 'Zend/zend_types.h' file not found`. Github shows?at least one other person had this problem?but for xcaddy builds instead of embedded app builds like mine. The recommended fix was to go download the PHP sources and try again.
My understanding is that that should only be needed for more complex build requirements, and shouldn't be needed for average PHP app binary builds (I think?).
I decided to pause the project here, as this was now going down a rabbit hole of potential complexity I didn't want. I'm not much of a Go or C dev, so everything going on here is a bit above my head!
Getting at least one build done is a success! I can tackle the others over time as the project and my understanding matures.
I still love FrankenPHP as an Octane driver and Caddy replacement all-in-one! But the binary builds are still a bit finicky.
Massive shoutout to Kevin Dunglas for being the mad lad to create this project in the first place!