Skip to content

Cross-compile PHP extensions and publish amd64/arm64 images - #58

Closed
jeremypoulter wants to merge 5 commits into
emoncms:masterfrom
jeremypoulter:cross-compile-php-extensions
Closed

jeremypoulter wants to merge 5 commits into
emoncms:masterfrom
jeremypoulter:cross-compile-php-extensions

Conversation

@jeremypoulter

@jeremypoulter jeremypoulter commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Publish a multi-platform linux/amd64 + linux/arm64 image.
  • Build the PHP extensions (mysqli, gettext, phpredis, Mosquitto-PHP) in a separate CI job. arm64 is cross-compiled with the aarch64-linux-gnu toolchain against headers taken from the target php:<version>-apache image, so no compiler runs under QEMU.
  • The runtime image copies in only the prebuilt .so files and installs libmosquitto1 instead of libmosquitto-dev. install_redis.sh, install_mosquitto.sh and docker-php-ext-install are removed.
  • Extension sources are pinned: phpredis 6.3.0 (df4fab2) and Mosquitto-PHP (426a08a).
  • The PHP base is pinned to the Debian trixie variant (php:<version>-apache-trixie, set by DEBIAN_SUITE) rather than whatever the untagged apache tag points to. It is resolved to a digest once, and every job uses that digest so the headers and ABI match.
  • Docker Hub vs GHCR tag routing is unchanged (openenergymonitor/emoncms:latest / :<version> when Docker Hub credentials exist). Pull requests build both platforms but do not push.
  • New: pushes to master now build and publish (previously publishing was manual-only via workflow_dispatch, which still works). Publishing runs are serialised so an older build cannot overwrite a newer :latest; superseded PR builds are cancelled.

QEMU is used only to assemble the arm64 image and run its load checks.

Workflow

  1. metadata: resolves the PHP image digest, checks for Docker Hub credentials and sets the tags.
  2. extensions (amd64/arm64 matrix): extracts the PHP SDK, builds the extensions and uploads them as artifacts. The build checks the ELF machine type, the get_module symbol, the absence of an RPATH and the libmosquitto soname.
  3. build-and-push: downloads both artifact sets, checks that all 8 .so files are present, then runs Buildx for both platforms.

Local builds

Local docker build / docker compose build now needs the extension artifacts to be built first. web/README.md documents the steps.

Testing

  • Built both artifact sets locally: 4 stripped x86-64 and 4 stripped AArch64 ELF shared objects.
  • Ran both images. PHP reports mysqli/gettext 8.4.25, redis 6.3.0 and mosquitto 0.5.1. ldd finds no missing libraries, and uname -m returns x86_64 and aarch64.
  • A dual-platform docker buildx build succeeds.
  • shellcheck ci/*.sh, actionlint and git diff --check pass.

@jeremypoulter

Copy link
Copy Markdown
Contributor Author

Closing for now; this work is continuing on the fork (jeremypoulter#3) while it's iterated on. I'll bring it back upstream once it has settled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant