frankenphp
frankenphp copied to clipboard
Create binary releases in addition to Docker images
We can use GoReleaser to build both and also provide .deb, .rpm, etc: https://goreleaser.com/cookbooks/cgo-and-crosscompiling/
WDYT @withinboredom @back-2-95?
I have a couple of thoughts:
- customizing Caddy plugins (ex: storage modules for certs in HA environments)
- customizing PHP extensions (which have to be built in ZTS mode?) (ex: WordPress)
How would we support this?
For 1., can we rely on xcaddy
to install frankenphp module? That might save us a ton of work/maintenance.
For 2., do we need to maintain our own packages per each OS for each extension?
Alternatively, we can write a tool to handle all-of-the-above, and provide an interface like Caddy does, where you can download a custom build.
Interestingly, last night, I thought of hooking into my self-hosted Docker registry and using tags to build extensions on demand. (docker pull registry.bottled.codes/dunglas/frankenphp:8.2-alpine-mysqli-gd
to get mysqli
and gd
extensions in the image, but I need to do some investigation, like how long is the docker pull
timeout 🤔)
This is not my area of expertise. But if there would be binary versions available, could those be just added to Docker images then?
Hi @dunglas,
I can contribute to this issue when you decide to implement it.
Hi! Don't hesitate to open a PR!
Great! Then let's find out what we want.
- Which GOOS do we want to support?
- Linux
- Darwin
- Windows
- Anything else?
- Which packages do we want to support?
-
.deb
-
.rpm
-
.apk
- Snapcraft
- Homebrew Taps
- AUR
- Anything else?
-
- Which Linux package registries do we want to use?
- fury.io
- jfrog.com
- Something else?
- Which Docker registries do we want to use?
- hub.docker.com
- ghcr.io
- jfrog.com
- Something else?
- Do we want to generate GitHub releases with GoReleaser? (this is a cool feature)
- Do we want to integrate GoReleaser with GitHub Actions?
- Anything else?
We can use one of my latest projects as a reference:
- https://github.com/ABGEO/mailtm/blob/main/.goreleaser.yaml
- https://github.com/ABGEO/mailtm/blob/main/.github/workflows/cd.yaml
Which GOOS do we want to support?
Yes! Windows is not supported yet but it's on the roadmap: #83.
Which packages do we want to support?
Sounds good
Which Linux package registries do we want to use?
No idea tbh, I don't know them. Couldn't we include FrankenPHP in Ubuntu (ppa?) and Debian official registries?
Which Docker registries do we want to use?
Just hub.docker.com (we already use it)
Do we want to generate GitHub releases with GoReleaser? (this is a cool feature)
Definitely (it's also what we do for Mercure)
Do we want to integrate GoReleaser with GitHub Actions?
Yes
Anything else?
It could be nice to provide a Helm chart too.
Here is our config for Mercure:
- Release script (support Go monorepo as we use here): https://github.com/dunglas/mercure/blob/main/release.sh
- Goreleaser config: https://github.com/dunglas/mercure/blob/main/.goreleaser.yml
- GHA: https://github.com/dunglas/mercure/blob/main/.github/workflows/cd.yml
Couldn't we include FrankenPHP in Ubuntu (ppa?) and Debian official registries?
It is a very, very long process to upload packages to official Linux Repositories (Debian - .deb
, RedHat .rpm
, Alpine - .apk
in our case).
The easiest way is to use our private registry, e.g fury.io offers unlimited public repositories for free. The user just has to add our repository to its package manager, e.g:
# Add repository to APT List.
cat > /etc/apt/sources.list.d/franken-php.list <<EOF
deb [trusted=yes] https://registry.frankenphp.dev/apt/ /
EOF
# APT Update & Install package.
apt update
apt install frankenphp
Also, cloudsmith.com seems pretty interesting, but I don't have experience with it.
Sounds good!
Was trying to compile frankenphp locally for myself todo some benchmarks. But could not achieve it to compile it myself. It would be really nice if in future Github Releases are providing binaries like it is done in Roadrunner: https://github.com/roadrunner-server/roadrunner/releases/tag/v2.11.4
But I see extensions
are making things a lot complicated in FrankenPHP.
@alexander-schranz, it's probably still too early to do some proper benchmarks. I did do some non-scientific ones, if you want to continue the discussion there.
Interesting strategy that could also work for us: https://www.bytebase.com/blog/how-to-cross-compile-with-cgo-use-goreleaser-and-github-action
Hi @dunglas,
We have some progress. I was able to build binaries for linux-x{64,32}
but I have some issues with darwin
. I have the following issue: ld: can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB) file '/usr/local/lib/libphp.so' for architecture x86_64
https://github.com/ABGEO/frankenphp/actions/runs/3480993831/jobs/5821508222#step:5:37
How do you compile PHP and FrankenPHP on MacOS? :smile:
You can check my GitHub Workflow and Actions here:
- https://github.com/ABGEO/frankenphp/blob/feat/goreleaser/.github/workflows/goreleaser-test.yaml#L78
- https://github.com/ABGEO/frankenphp/tree/feat/goreleaser/.github/actions/php/darwin
Great! Thank you.
This is because of https://github.com/php/php-src/issues/8533. https://github.com/ABGEO/frankenphp/pull/1 should fix the problem.
Unfortunately, this doesn't help. We have the same error :cry:
if you could just do,
wget http://frakenphp-linux64.tar.gz tar -xzf frakenphp-linux64.tar.gz ./php
a lot of devops guys would be so happy, makes it so easy with ansible, custom Docker and whatever comes next. deb/rpm/whatever are nice to haves, but a binary in a tar.gz archive would solve almost all use cases. Java/JDK did this long back and makes me want to write in java as it is so easy to package.
Hello,
I'm interested in binary release as well, long time Mercure user and we could probably move some projects to Franken and have a beta test on the traffic yay!
Thanks!
Count me in as well. I compiled a binary, but could not get it to work correctly (it served files, but not PHP). Given the development phase of the project, I didn't know if it was me or the code, and so I couldn't file any meaningful issue reports as a result. A known binary release would help with this.
I really wish there was some way to statically build PHP and bundle it with this. I suspect many of the issues will be the dynamic linking nature of PHP vs. the static nature of frankenphp.
I'm on it! https://static-php-cli.zhamao.me/ should help.
Oh man. I didn't know that project existed and has been something I've been looking for on-and-off for years.
If you follow the goreleaser path, please include brew and nixpkgs as a package output: it will enable rootless installs but with the confort of a package manager (not the OS one).
I don't think bundling php-cli is as important as providing binary releases. I'd love to give this a try, but there's very little reason for me to use docker in a php stack.
I could also imagine running into a lot of issues when trying to bundle php extensions that aren't available for every OS (for example php-semaphore or php-ldap). This should not necessarily prevent binary releases, I'm sure most people wouldn't mind installing php-cli.
Despite the name of the project, static-php-cli supports other SAPI than CLI, and allows to create standalone binaries of FrankenPHP (without the CLI SAPI). Here is a working PR with FrankenPHP binaries available for Linux and Mac: https://github.com/dunglas/frankenphp/pull/198
Thanks for the link, but is it possible to use FrankenPHP with the locally installed php cli version, or do we need to build from source if there are extensions missing in the released build? E.g. ldap, semaphore, xdebug for debugging, etc?
I see that using a local php installation is the preferred way, but no information on using binary releases with the local php installation.
FrankenPHP doesn't use PHP CLI at all. It provides its own SAPI (as the Apache module, PHP FPM or PHP CLI itself).
FrankenPHP can be used with a local installation of libphp
that will be loaded dynamically, as long as PHP is compiled with the proper options (especially, ZTS): https://github.com/dunglas/frankenphp/blob/main/docs/compile.md#linux
For instance, it's possible to use a dynamic build of PHP with the libphp.so
provided by the official Docker images for PHP (ZTS variant) and by Setup PHP (that we use in our own CI) and PHP Builder). However most Linux distributions don't provide ZTS variants of their PHP packages (yet).
PHP extensions can be dynamically loaded my (Franken)PHP as usual when using dynamic builds.
The official FrankenPHP Docker images use dynamic builds. I currently don't plan to distribute official standalone binaries built dynamically yet because it will cause more confusion than anything else (they will don't work on most popular Linux distros). However, as we already build dynamic builds for Docker images and for our own tests, I may made them available as CI artifacts for advanced users, as we already do for dynamic builds.
Ah, that clears it up. Thanks for taking the time to respond - for this project and your contributions in general. I'll be giving this a try and eagerly wait for a production ready release. It'll simplify running running symfony apps with mercure a lot instead of having to run multiple servers (and a reverse proxy for mercure urls).
@dunglas sorry to resurrect this, I've integrated ldap support into static-php-cli, but imap support may be a while ahead and xdebug will never be bundled with it because of its dynamic nature.
This may be a stupid question, but is it enough to compile a ZTS version of php ourselves and use it in combination with the official extension packages? If it's possible, would all the built in extensions (like mbstring, ldap, imap, openssl, zlib, etc.) have to be compiled together with libphp.so, or is a base compilation going to work with the official extensions anyway?
I'm looking for a way for FrankenPHP to serve our pages, but it would be nice if we didn't have to run apache or nginx on a different port in case I'd have to debug something. Compiling all extensions in shared ZTS mode would take enormous effort in case of an upgrade, so I'd rather avoid that too. Static build would be fine, except for the case of debugging a script.