feat(aloft): first-party official docker images and supporting utilities#2004
feat(aloft): first-party official docker images and supporting utilities#2004iamdadmin wants to merge 4 commits intotempestphp:3.xfrom
Conversation
…al docker images for TempestPHP
…initial, moved ServeCommand back to router package
|
|
While this is a working start, there's more to be done on making a fixed bill-of-materials, pinning and tracing versions in each build. At the moment we're just inheriting frankenphp and plopping it in a distroless image which works, but we can do better. Alpine is out for this reason https://frankenphp.dev/docs/performance/#dont-use-musl
So that brings us to options.
Downsides - php-zts packages aren't in Sury repo and will have to be built from source, Bazel really wants to deploy from repos, and it's a fairly big fork to maintain
Downsides - The tool is lower-level but can make fixed-file systems from package lists. We'll have to do some work to wrap a file-pinning BOM around it, and maintain that. Again, Sury repo doesn't do php-zts so we'd have to build PHP from source. We'd have to make and maintain it, breaking fairly fresh ground.
Downsides - Adopting Canonical may not be the wisest due to their not entirely FOSS-friendly choices at times (i.e. insisting on Snap instead of using Flatpak) and Chisel cannot work with non-Ubuntu repos. So we'd have to build php-zts and frankenphp from source and manage all those deps, which is a bit less ideal. That means no single BOM.
Downsides - relying on community maintainers to bump the php-zts and frankenphp packages, although granted, we could potentially submit PRs if we needed to. Learning curve, I'm willing to dive in, but it is it's own whole thing. My suggestionGiven all of the above, my feeling is that NixOS is probably actually the best way to go. We can inject our Caddyfile, and Nix can build an OCI-compatible image that we can just import to Docker or podman locally, or push to a registry. We'd produce a flake file for each build, and then as with composer, a flake.lock file is generated with a fixed package list. If we get a security advisory in dependencies, we can bump individual files and re-build. When frankenphp and/or php gets a bump, aka our 'primary' packages, we could either manage with git tags so we can inspect point in time, or we can literally duplicate the original flake file side-by-side in another folder or something. |
…evelopment, fixed issue in stage-files under amd64
|
Okay, I've done a test with Nix, and there's some constraints that I think rule it out.
On to the next one! |
aidan-casey
left a comment
There was a problem hiding this comment.
Hey, @iamdadmin! I apologize for only just now getting around to this, there's a lot to review here. 🙂
First off, I appreciate the work you have put into this. Thank you!
Generally, as I look at this PR, I'm less concerned with the substance of it than I am of the complexity of it.
For example, let's envision the ideal user experience as something like:
# Publishes the Docker stubs to the root of our project.
tempest aloft:install
# Starts a dev environment.
docker compose up -d
# Builds a production image.
docker build .If we are publishing the stubs to the root of our project, is the average user going to be able to figure out how to add a PHP extension easily? Will they be able to debug a distroless container with little to no logs?
I'm thinking we might need to simplify this further, which might mean publishing a base build to the Docker registry and pulling from that for our stub. That would create an issue with distroless, however.
Dunno, I'm open to discussion on all this, just spitballing as I think about the dev experience.
There was a problem hiding this comment.
I think I'd scratch this file, personally. Let's assume the end user with Docker knows how to run this with Docker and provide a sensible docker-compose default.
|
|
||
| {$CADDY_EXTRA_CONFIG} | ||
|
|
||
| {$CADDY_SERVER_NAME:localhost}:{$CADDY_HTTP_PORT:8000}, {$CADDY_SERVER_NAME:localhost}:{$CADDY_HTTPS_PORT:8443} { |
There was a problem hiding this comment.
I think you can leave off ports here because they are already defined globally above.
There was a problem hiding this comment.
My gut is that this adds a complexity that we're not after here and we either need to extract this out to a separate build process and publish to a registry or simplify.
There was a problem hiding this comment.
I'm going back and forth on the distroless. I really like the idea in concept, but I have a few concerns:
- I think the ideal world is that these are stubs we are publishing into the project for someone to use/customize. These would be a lot of stubs to publish and I'm guessing the average user is going to get overwhelmed and/or not understand what is going on here.
- The resulting image is still pretty large. Knowing the issues with MUSL, I'd be curious if we could get the same/less size using RedHat UBI or something.
- I am just imagining a situation where someone submits a bug report about something with the Docker image and we want logs or something.
There was a problem hiding this comment.
We probably need to track the env variables somewhere as there are quite a few at play here.
|
|
||
| RUN curl -sSLf \ | ||
| -o /usr/local/bin/install-php-extensions \ | ||
| https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \ |
There was a problem hiding this comment.
I concur with previous comments about latest. We should probably pin things like this and verify the hash.
There was a problem hiding this comment.
| EXPOSE 8000 | ||
| EXPOSE 8443 | ||
| EXPOSE 8443/udp | ||
| EXPOSE 2019 |
There was a problem hiding this comment.
Any real reason to expose this?
| # Build-time arguments — set by bake.hcl, can be overridden individually | ||
| ARG FRANKENPHP_VERSION=1.11.2 | ||
| ARG PHP_VERSION=8.5.3 | ||
| ARG BASE_IMAGE=dunglas/frankenphp:${FRANKENPHP_VERSION}-php${PHP_VERSION} |
There was a problem hiding this comment.
I'd be half tempted to pin the version and reduce flexibility here.
How about RedHat's UBI? |
No worries at all, it helps me as much as it helps the community as I intend to use it myself. Equally, if I am not going in the direction wanted for Tempest, that's also fine, I'm not going to try to force it on you or anything and if what I want doesn't match I will just make my own package and use it :) So please, don't hold anything back or worry about wording, I won't be offended.
I agree, this implementation is more fragile than I was aiming for.
You're right that the PHP extensions issue is big. On the distroless side, the debug container has a shell, and we can figure out tweaks like logging configs, or even make sure all the logs go into /var/logs and we make that a container path so they're literally written in /logs/aloft/, or they can be viewed on the shell of course. We already set environment in .env so that can be utilised, or we can just turn all logs on in debug with a 7 day rotation/retention and all off in the distroless PROD image. I think the goal to aim for is that both images are in the registry for those who want no changes, or extendable locally.
I agree that this won't work in it's current iteration. My next test is:
What this means is that one will be able to do ./tempest aloft:build --with-phpExtensions "yml,other-extension,another-one,whatever" --composeInternally the --compose flag will just run ./tempest aloft:compose which can be used independently with the registry images. What this will do is automate the docker-build, locally, and with the --compose flag also build a docker-compose for those who need the full stack. For the end user? One or two simple commands. For us? We can use it in CI/CD to make SBOM-traceable images for each version pairing of php/frankenphp. We should probably envision some kind of version strategy for example for when Tempest itself moves past PHP8.5 to PHP8.6 - at this point maybe we archive all older versions from the registry itself, excepting the very last PHP8.5.x and frankenphp image, while retaining the SBOMs in the github repo in case people need to build them locally for their own needs, to keep storage costs managed etc. Looking forward, we should probably also tie in a package security check and actively remove images with known defects, I'm not sure on that mechanism yet and suspect best to put that in a second release as this commit will just get huge otherwise. I'm working on the Dagger workflow at the moment, given I have a working Dockerfile it hopefully won't take too much effort to convert it into Dagger commands, and test. Will keep you posted. |
Closes #1983
Introducing tempestphp/aloft
Or, at least, if you like the name! 'aloft' was my idea for this pseudo-package because it invokes imagery of things in the sky ... among the clouds ... and docker images are very 'cloudy'.
I'll write out some Q&A in another reply, probably tomorrow now, so you can understand my choices in the design and production of this image, including the answers to "why not alpine?", "why rootless?" and "why distroless?".
Initial draft PR includes
./tempest serve --aloftto pull and run the docker image to serve a dev server, alongside php dev server remaining primaryThings to be checked
Still to be done
Future roadmap