frankenphp: ship xorriso for cloud-init NoCloud seed ISOs #39

Merged
geusebio merged 3 commits from feat/frankenphp-xorriso into main 2026-08-08 01:54:10 +00:00
Owner

Adds xorriso to the FrankenPHP base image (matthewbaggett/frankenphp:*), ~1MiB including its libburn/libisofs/libisoburn deps.

Why here and not downstream: Someones.Computer builds a per-VM cloud-init NoCloud seed ISO (volid CIDATA carrying user-data/meta-data/network-config) with

xorriso -as mkisofs -output seed.iso -volid CIDATA -joliet -rational-rock user-data meta-data network-config

Its final Dockerfile stage is deliberately RUN-free — every instruction is a COPY, so the foreign-arch (arm64) leg of the multi-arch build executes nothing and needs no QEMU. Its current stopgap RUN apk add --no-cache xorriso undoes exactly that, and the builder stage can't help because it's FROM --platform=$BUILDPLATFORM (wrong arch). Once this ships, that repo should drop the stopgap and get its RUN-free final stage back.

The validate.d check builds a real ISO rather than probing for the binary: the load-bearing part is -joliet/-rational-rock, without which plain ISO 9660 Level 1 (8.3, uppercase, A-Z 0-9 _) cannot represent user-data at all and cloud-init would never find it. The check asserts the CIDATA label and that all three files extract back out under their exact names with intact contents.

Verified locally: ./test frankenphp-85-assertions is green, new check included.

Follow-up worth considering (separate repo): the CI runner image ghcr.io/matthewbaggett/act-runner:php8.5 (actions/Github-Actions-Runner) also lacks xorriso, so tests wanting a genuinely generated ISO must mock it.

🤖 Generated with Claude Code

Adds `xorriso` to the FrankenPHP base image (`matthewbaggett/frankenphp:*`), ~1MiB including its libburn/libisofs/libisoburn deps. **Why here and not downstream:** Someones.Computer builds a per-VM cloud-init NoCloud seed ISO (volid `CIDATA` carrying `user-data`/`meta-data`/`network-config`) with xorriso -as mkisofs -output seed.iso -volid CIDATA -joliet -rational-rock user-data meta-data network-config Its final Dockerfile stage is deliberately RUN-free — every instruction is a COPY, so the foreign-arch (arm64) leg of the multi-arch build executes nothing and needs no QEMU. Its current stopgap `RUN apk add --no-cache xorriso` undoes exactly that, and the builder stage can't help because it's `FROM --platform=$BUILDPLATFORM` (wrong arch). Once this ships, that repo should drop the stopgap and get its RUN-free final stage back. **The validate.d check builds a real ISO** rather than probing for the binary: the load-bearing part is `-joliet`/`-rational-rock`, without which plain ISO 9660 Level 1 (8.3, uppercase, `A-Z 0-9 _`) cannot represent `user-data` at all and cloud-init would never find it. The check asserts the `CIDATA` label and that all three files extract back out under their exact names with intact contents. Verified locally: `./test frankenphp-85-assertions` is green, new check included. Follow-up worth considering (separate repo): the CI runner image `ghcr.io/matthewbaggett/act-runner:php8.5` (actions/Github-Actions-Runner) also lacks xorriso, so tests wanting a genuinely generated ISO must mock it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
frankenphp: ship xorriso for cloud-init NoCloud seed ISOs
Some checks failed
Build / Run container tests (push) Failing after 11m6s
Build / Build (push) Has been skipped
89ed93b16c
Downstream projects (Someones.Computer) provision Alpine VMs on Proxmox
and build a per-machine NoCloud seed ISO -- volid CIDATA, carrying
user-data / meta-data / network-config -- with:

    xorriso -as mkisofs -output seed.iso -volid CIDATA \
        -joliet -rational-rock user-data meta-data network-config

Their final image stage is deliberately RUN-free so the foreign-arch leg
of the multi-arch build executes nothing and needs no QEMU, which means
they cannot `apk add xorriso` themselves; the builder stage is
--platform=$BUILDPLATFORM and would install the wrong arch. So the tool
belongs in this base. Costs ~1MiB (xorriso + libburn/libisofs/libisoburn).

The validate.d check builds a real seed ISO rather than just probing for
the binary, because the load-bearing part is -joliet/-rational-rock:
plain ISO 9660 Level 1 names are 8.3, uppercase, A-Z 0-9 _ only, so
`user-data` cannot be represented at all and cloud-init would never find
it. The check asserts the CIDATA label and that all three files come
back out under their exact names with intact contents.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

CI run 297 (89ed93b) failed, but not because of this change: the frankenphp-84-healthchecks build died in the shared INSTALL_FRANKENPHP apk step with ERROR: php-zts-apcu-5.1.28p84-r0: DNS: transient error (try again later) while fetching from pkg.henderkes.com. That is a transient network failure on a package unrelated to xorriso (three other runs were in flight on the shared daemon at the time), and the xorriso validate script never executed. Pushing an empty commit to re-run.

CI run 297 (89ed93b) failed, but not because of this change: the `frankenphp-84-healthchecks` build died in the shared `INSTALL_FRANKENPHP` apk step with `ERROR: php-zts-apcu-5.1.28p84-r0: DNS: transient error (try again later)` while fetching from pkg.henderkes.com. That is a transient network failure on a package unrelated to xorriso (three other runs were in flight on the shared daemon at the time), and the xorriso validate script never executed. Pushing an empty commit to re-run.
ci: retry after transient DNS failure fetching php-zts-apcu
Some checks failed
Build / Run container tests (push) Failing after 30m34s
Build / Build (push) Has been skipped
2cd5e20b93
Run 297 failed in the frankenphp-84 apk step with a pkg.henderkes.com
DNS transient error, unrelated to this change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

Run 301 (2cd5e20, the retry) failed, and again not because of this change. This time every image built cleanly and the xorriso validation demonstrably passed on all FrankenPHP variants during the build:

  • (41/41) Installing xorriso (1.5.6-r0) on 82/83/84/85
  • /etc/validate.d/xorriso.sh: volid CIDATA detected as expected; user-data, meta-data, network-config all round-trip OK; Validation passed

The run then died in the healthcheck phase with Error response from daemon: failed to set up container networking: Could not attach to network docker_default: ... network docker_default not found — a concurrent run's cleanup removed the shared compose network out from under this run's container startup (both use the compose project name docker on the shared daemon). Will re-run once the daemon is quiet.

Run 301 (2cd5e20, the retry) failed, and again not because of this change. This time every image built cleanly and the xorriso validation demonstrably passed on all FrankenPHP variants during the build: - `(41/41) Installing xorriso (1.5.6-r0)` on 82/83/84/85 - `/etc/validate.d/xorriso.sh`: volid `CIDATA` detected as expected; `user-data`, `meta-data`, `network-config` all round-trip OK; `Validation passed` The run then died in the healthcheck phase with `Error response from daemon: failed to set up container networking: Could not attach to network docker_default: ... network docker_default not found` — a concurrent run's cleanup removed the shared compose network out from under this run's container startup (both use the compose project name `docker` on the shared daemon). Will re-run once the daemon is quiet.
Author
Owner

Downstream cleanup is tracked in Grey.ooo/Someones.Computer#389: once this merges and the image republishes, that repo deletes its pinned RUN apk add --no-cache xorriso=1.5.6-r0 stopgap and gets its copy-only (QEMU-free) final stage back.

Downstream cleanup is tracked in [Grey.ooo/Someones.Computer#389](https://git.grey.ooo/Grey.ooo/Someones.Computer/issues/389): once this merges and the image republishes, that repo deletes its pinned `RUN apk add --no-cache xorriso=1.5.6-r0` stopgap and gets its copy-only (QEMU-free) final stage back.
Merge origin/main into feat/frankenphp-xorriso
Some checks failed
Build / Run container tests (push) Failing after 12m14s
Build / Build (push) Has been skipped
1e721ef1dd
Combines the xorriso addition with main's elf-stack-size fix and stock
Caddyfile removal in the same apk layer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

Fixed the merge conflict with main: FrankenPHP.Dockerfile now carries both this PR's xorriso addition and main's elf-stack-size/stock-Caddyfile changes in the same apk layer (merge commit 1e721ef).

Re the previous red run (run 301): every image built green; the job died while the healthcheck containers were starting, with Could not attach to network docker_default: network not found — a concurrent run's compose teardown on the shared daemon removed the network mid-startup. Infrastructure, not this change.

🤖 Generated with Claude Code

Fixed the merge conflict with main: `FrankenPHP.Dockerfile` now carries both this PR's `xorriso` addition and main's `elf-stack-size`/stock-Caddyfile changes in the same apk layer (merge commit 1e721ef). Re the previous red run ([run 301](https://git.grey.ooo/Grey.ooo/docker/actions/runs/301)): every image built green; the job died while the healthcheck containers were starting, with `Could not attach to network docker_default: network not found` — a concurrent run's compose teardown on the shared daemon removed the network mid-startup. Infrastructure, not this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Grey.ooo/docker!39
No description provided.