docker-php icon indicating copy to clipboard operation
docker-php copied to clipboard

Add FrankenPHP support

Open jaydrogers opened this issue 1 year ago β€’ 20 comments

Franken PHP

πŸš€ What this PR does

  • [x] Adds FrankenPHP be offered as a variation
  • [ ] Allow the PHP minor version to be selected with FrankenPHP
  • [ ] Allow the "autorun" scripts and other custom init scripts to run before bringing up FrankenPHP
  • [ ] Allow the PHP_ environment variables from other Server Side Up images to work with FrankenPHP

Create documentation

  • [ ] Laravel + FrankenPHP
  • [ ] Customizing start up with FrankenPHP
  • [ ] Installing custom PHP extensions with FrankenPHP

Checklist

  • [ ] Ensure SSL_MODE works as other variations
  • [ ] Ensure custom extensions can be installed like other variations

jaydrogers avatar Feb 08 '24 00:02 jaydrogers

This would be super cool to have! Great work on this so far!

Sammyjo20 avatar May 07 '24 14:05 Sammyjo20

Deploying serversideup-php with Β Cloudflare Pages Β Cloudflare Pages

Latest commit: f7cd1d7
Status:Β βœ…Β  Deploy successful!
Preview URL: https://e2aee8a9.serversideup-php.pages.dev
Branch Preview URL: https://280-create-a-frankenphp-vari.serversideup-php.pages.dev

View logs

This would really be a nice addition..

GunniBusch avatar Jun 01 '24 16:06 GunniBusch

This will be a wonderful addition!

thinkstylestudio avatar Jun 27 '24 03:06 thinkstylestudio

This would be a great feature! πŸš€ Any updates here?

mihai-burduselu-ptt avatar Aug 27 '24 15:08 mihai-burduselu-ptt

Not sure how I missed your message @mihai-burduselu-ptt.

I am getting v3.4 updates out the door for the last major optimizations for fpm-nginx. Then it's FrankenPHP time 😎

jaydrogers avatar Sep 27 '24 17:09 jaydrogers

This is a great addition to serversideup. Any updates regarding frankenPHP?

hstoenescu avatar Nov 18 '24 14:11 hstoenescu

I'd like to see FrankenPHP added too.

hookenz avatar Nov 18 '24 23:11 hookenz

Thanks for your patience, all! I'm looking for the future of PHP and I really hope FrankenPHP is it.

I've been very busy with Spin and once I get this big release of Spin v3 out the door, then I will be swinging to this.

Exploring FrankenPHP is very important to me and I will definitely be getting this accomplished πŸ’―

jaydrogers avatar Nov 22 '24 19:11 jaydrogers

I am back from holiday break and will be evaluating this for v3.6. I have taken about 3 attempts at this and have paused and deleted each time πŸ™ƒπŸ”₯

My challenge is I believe I need to compile FrankenPHP from source so I can maintain the "single source of truth" from the official Docker PHP images. I need to spend more time ensuring this is the way, since I haven't compiled a Go app in my life πŸ˜…

I will keep everyone posted once I have an update but please chime in below if you have any thoughts πŸ™

jaydrogers avatar Jan 07 '25 16:01 jaydrogers

@jaydrogers Not sure if this is feasible? The frankenphp images are based on the official docker images and add their stuff on top, so the php images would still be the source of truth? It’s additional work to keep the build working, which is done by the frankenphp maintainers anyway. Since it’s based on official docker images, you should be able to do anything you want with the frankenphp images, don’t you?

That being said, I have no deep understanding about what you’re adding, so my opinion might be invalid :sweat_smile:

thomasaull avatar Jan 07 '25 16:01 thomasaull

Thanks for chiming in! Yes, you're totally right -- and I've tried this path. This might be a complicated for a single GitHub issue post, but here is an attempt on simpliying a few critical background parts:

  1. I use https://www.php.net/releases/active.php as my "source of truth" in get-php-versions.sh
  2. This builds a php-versions.yml file (base config is here)

If a new version of PHP is made available and FrankenPHP hasn't released that version yet, the build will fail.

This adds two layers of dependencies for all Server Side Up images (if they are FrankenPHP or not):

  1. Official PHP images must be built
  2. FrankenPHP must have images built with the EXACT patches that we're trying to use

This is where I hit my head against the wall and decided to take a break and circle back later πŸ˜ƒ

I believe my latest theory was to use Multi-stage builds take the official build PHP image, check out a specific version of FrankenPHP, then compile it following their methods -- but I don't want to re-invent the wheel on compiling either πŸ˜…

Full build process

https://github.com/serversideup/docker-php/blob/4807f9881f4edcb0d70bf16974e4a5f7a1a18698/.github/workflows/service_docker-build-and-publish.yml#L41-L169

jaydrogers avatar Jan 07 '25 16:01 jaydrogers

@jaydrogers Thanks for the explaination, I definitely see your point. I guess it’s a trade of between path a) or b) where both require extra work then πŸ˜…

If it where up to me to decide, I'd probably add the additional dependency of frankenphp to the automated pipeline: Additionally check the frankenphp releases and only build this flavour of serversideup if the release is available. Again I might be missing something from a lack of knowledge.

Also the frankenphp images apparently are automatically built when a new php image is available: https://frankenphp.dev/docs/docker/#updates

thomasaull avatar Jan 08 '25 10:01 thomasaull

I like @thomasaull's suggestions above. I'm re-evaluating switching back to serversideup/php since things have improved a lot since my last evaluation and I was just considering if there was a frankenphp variation as I personally use caddy in my own image and would like to keep using a caddy variant over nginx or apache.

joshmanders avatar Jan 11 '25 00:01 joshmanders

@jaydrogers - eager to get this going I've decided to give you a hand.

Here's a PR that gets us a bit further down the road. https://github.com/serversideup/docker-php/pull/527

hookenz avatar Apr 11 '25 01:04 hookenz

@jaydrogers I've been thinking about your dependency problem and I think you should build off the official frankenphp image rather than build franken yourself.

According to this link: https://frankenphp.dev/docs/docker/#updates

Like yours, the images will be built automatically with each PHP released.
So maybe your images just need to kick off a bit after that. According to the FrankenPHP website 4am UTC? Although, we don't know how long it might take to appear on dockerhub.

So I think probably you should have the images build independently of each other so the whole build doesn't fail. And then publish on your website which version is available for each. Most of the time I would expect it to be the latest. But sometimes it might be held back. I guess you can have the script email you if there is a problem.

Regarding the images apparently the tags follow this pattern:

dunglas/frankenphp:<frankenphp-version>-php<php-version>-<os>

<frankenphp-version> and <php-version> are version numbers of FrankenPHP and PHP respectively, ranging from major (e.g. 1), minor (e.g. 1.2) to patch versions (e.g. 1.2.3).
<os> is either bookworm (for Debian Bookworm) or alpine (for the latest stable version of Alpine).

You can either query the dockerhub api via curl and some scripting magic or use this tool. https://github.com/docker/hub-tool

Script adapted from the internet.

 #!/bin/sh

listTags() {
    repo="$1"
    size="${2:-25}"
    page="${3:-1}"

    if [ -z "$repo" ]; then
        echo "Usage: listTags <repoName> [size] [pageIndex]" >&2
        return 1
    fi

    #curl "https://hub.docker.com/v2/repositories/${repo}/tags?page=${page}&page_size=${size}"
    curl -s "https://hub.docker.com/v2/repositories/${repo}/tags?page=${page}&page_size=${size}" 2>/dev/null | jq -r '.results[].name' | sort
}

listTags dunglas/frankenphp 10 1

Just some thoughts. Very happy to help out. If you want some more in depth discussion or a sounding board on it let me know. I haven't delved very deep into your build process as yet.

hookenz avatar Apr 15 '25 01:04 hookenz

Hi, any update on this?

sawirricardo avatar May 17 '25 12:05 sawirricardo

Hi, any update on this?

I think @jaydrogers has been quite busy. So have I. It's certainly not forgotten. I will be needing this soon also.

hookenz avatar May 19 '25 03:05 hookenz

Hi, @jaydrogers . Any roadmap or updates on this? πŸ˜„

mihai-burduselu-ptt avatar May 29 '25 14:05 mihai-burduselu-ptt

Haven't forgotten. Working on a big update that's related to this, then I will swing back.

Stay tuned πŸ˜ƒπŸ‘

jaydrogers avatar May 29 '25 14:05 jaydrogers

Just checking in on this, thanks!

juddisjudd avatar Jul 21 '25 17:07 juddisjudd

I'm out of the office this week, but I plan on doing serversideup/php items once I get back next week πŸ‘

jaydrogers avatar Jul 21 '25 18:07 jaydrogers

Do you need some help on this? I have some time next week to pick this up if needed.

django23 avatar Jul 24 '25 09:07 django23

Huge update πŸ₯³

Thank you so much for your patience, all!

Just wanted to let you know that supporting FrankenPHP is very important to serversideup/php. I finally had the time to sit down and deep into this. Here's where I'm at:

FrankenPHP is now compiled by source πŸ€“

I never compiled a Go app in my life, but I was able to go through the official Dockerfiles and understand what's going on. Good news is I'm able to get Alpine and Debian to build from a single Dockerfile, making it pretty easy to maintain.

πŸ‘€ Extra features compared to official FrankenPHP

Since we're able to compile the binary ourselves, it opens up a ton of possibility:

Compile with any OS and any PHP version

I spent a crapload of time refactoring my "php-versions.yml" file. This allows us to set advanced rules like:

  • Choosing what PHP versions a variation supports
  • Setting what operating systems each PHP version supports

This means that we can run FrankenPHP on a version pinned operating system (alpine3.22, alpine3.21, etc). Oh, and don't worry -- I also have "family level" tags so alpine will be tagged on the latest version of alpine or but it still allows you to version pin if you want. πŸ€ͺ

We'll actually be able to run FrankenPHP on more operating systems compared to their original offering.

Unprivileged by default

Running as the www-data user by default is very important for security. Just like our other variations, we will run on 8080 or8443 by default. I am hoping I don't run into any issues with this, but so far my tests are coming back well.

All serversideup scripts will be included

One of my favorite things about the serversideup/php images are the automation and helper scripts that are provided. All of these scripts will be inside of and fully supported in the serversideup/php:frankenphp image πŸš€

πŸ‘‰ Next Steps

There's still A LOT left for me to do. The first comment will continuously be updated with my task status. I want to make sure FrankenPHP is offering the same features as we do in our fpm-nginx image. This will also be my first time writing a Caddyfile (sorry, don't hate -- I've always used Traefik πŸ˜…) so please bear with me as I learn this process.

I pushed up my code in case someone wants to start looking at my approach so far. If you're interested in helping out, just please comment below with your proposed changes before rampaging on a PR. There's a lot of moving parts in this release, so I just want to respect your time. I need to fully understand the proposed change before it can be merged.

Here's a PHP info page below to show proof that I'm not bluffing πŸ˜†

Looking forward to getting this out the door! Thanks again for your patience πŸ‘

image

jaydrogers avatar Aug 23 '25 12:08 jaydrogers

@jaydrogers, will this variation still require changing permissions during the build phase?

brufdev avatar Aug 23 '25 16:08 brufdev

Yup, it will be unprivileged by default (for best security), but you can add "USER root" if you need to gain root permissions.

Also, remember, you can use "docker exec -u root" if you need to get root access to an unprivileged container for debugging πŸ€“

jaydrogers avatar Aug 23 '25 16:08 jaydrogers

πŸš€ FrankenPHP is ready for testing

πŸ‘‡ How to test

See the top comment on this PR for latest updates, resources, and progress.

πŸ› Have an issue?

Thanks for your patience and encouragement, y'all ✌️

jaydrogers avatar Aug 28 '25 21:08 jaydrogers

A quick chat with GPT5 said this on Caddyfile. @jaydrogers

Key takeaway for me is everything is good, but then the dot env side of things comes off like it needs double checking in terms of security atleast

image

Here is what it suggested

(security) {
	@rejected path *.bak *.conf *.dist *.fla *.ini *.inc *.inci *.log *.orig *.psd *.sh *.sql *.swo *.swp *.swop
	# Explicit root-level & nested dotfiles and common secrets
	@secrets path .env .env.* .git .git/* .gitignore .gitattributes composer.* package-lock.json yarn.lock pnpm-lock.yaml

	respond @rejected 403
	respond @secrets 403

	header {
		defer
		X-Frame-Options "SAMEORIGIN"        # keep for legacy UAs
		X-Content-Type-Options "nosniff"
		Referrer-Policy "strict-origin-when-cross-origin"
		-Server
		-X-Powered-By
		# Modern hardening (tune to your app)
		Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; upgrade-insecure-requests"
		Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=()"
		Cross-Origin-Resource-Policy "same-site"
		Cross-Origin-Opener-Policy "same-origin"
	}
}

(security-https) {
	header {
		defer
		Strict-Transport-Security "max-age=31536000; includeSubDomains"
		# add "; preload" ONLY if you control all subdomains and plan to submit to the preload list
	}
}

And also hide at the file server level:

(app-common) {
	root * {$CADDY_APP_PUBLIC_PATH:/var/www/html/public}
	encode zstd br gzip

	# Access log level import stays
	import log-level/address/{$LOG_OUTPUT_LEVEL:info}.caddyfile

	@health { path /healthcheck }
	respond @health "OK" 200
	log_skip @health

	php_server {
		{$CADDY_PHP_SERVER_OPTIONS}
	}

	# Never serve these if they slip past routing
	file_server {
		hide .env .env.* .git .git/* .gitignore .gitattributes composer.* package-lock.json yarn.lock pnpm-lock.yaml
	}

	import performance
	import security

	{$CADDY_SERVER_EXTRA_DIRECTIVES}
}

I'm no caddy expert. Just trying to help if it's any help at all to get this out as safely and soon as possible.

Thanks

opheus2 avatar Aug 28 '25 21:08 opheus2

I'm definitely open for discussion on how to improve the Caddyfile (because I just learned Caddy this week), but I might yield the proposals to improvements by humans with real experience.

I am all for using AI as an assistant, but extremely hesitant to let it take the wheel on improvements (because I could respond with "Are you sure?" and it would likely 2nd guess itself anyways πŸ€ͺ)

If anyone else can help decipher these proposals, I am all ears πŸ™

jaydrogers avatar Aug 28 '25 21:08 jaydrogers

Been using this alpha for the last 40 mins and it was almost a drop in replacement for fpm-nginx. The only change I had to make was removing an explicit nginx permissions call leftover in my Dockerfile.

I'm sure there are probably minor tweaks that will be made before release, but this seems pretty solid so far. Great work @jaydrogers

tomschlick avatar Aug 29 '25 00:08 tomschlick