Skip to content

ci: publish multi-arch (amd64 + arm64) container images - #37

Merged
brtkwr merged 1 commit into
mainfrom
ci/multi-arch-images
Sep 18, 2026
Merged

brtkwr merged 1 commit into
mainfrom
ci/multi-arch-images

Conversation

@brtkwr

@brtkwr brtkwr commented Sep 18, 2026

Copy link
Copy Markdown
Owner

ghcr.io/brtkwr/magento-base and ghcr.io/brtkwr/magento are amd64-only today, so on Apple Silicon they run under QEMU and everything is slow. This makes both publish a manifest list with linux/amd64 and linux/arm64.

How

Each of the four docker/build-push-action steps (base and Magento, in ci.yaml and release.yaml) becomes a matrix over platform, with a dependent merge job:

  • The per-platform job runs on a native runner — ubuntu-latest for amd64, ubuntu-24.04-arm for arm64. No QEMU: a Magento composer install plus sample data under emulation is far too slow, and arm runners are free on public repos.
  • It pushes by digest (push-by-digest=true,name-canonical=true, no tags:) and uploads the digest as an artifact.
  • The merge job downloads the digests and runs docker buildx imagetools create to assemble the manifest list under the real tags. This is the pattern from the docker/build-push-action multi-platform docs.

Details worth noting:

  • The Magento image builds FROM the base, so it now depends on docker-base-merge rather than the per-platform base jobs — the base manifest list has to exist before an arm64 Magento build can resolve its parent.
  • Each platform (and, for Magento, each version) gets its own type=gha cache scope, otherwise the jobs overwrite each other's cache.
  • The composer_auth secret is untouched in both files: still the inline JSON string in ci.yaml, still the jq-generated auth.json file in release.yaml.
  • Dockerfiles are unchanged. The base is php:8.2-apache plus apt packages and PHP extensions built from source, with composer copied from the multi-arch composer:2 image; the Magento file is composer packages only. Nothing pulls an x86 binary.
  • # Build: comment lines in both Dockerfiles and the buildx examples in the README now show --platform linux/amd64,linux/arm64.

What this PR run can and cannot prove

ci.yaml's image jobs only run on pushes to main (github.event_name == 'push' && github.ref == 'refs/heads/main'), so on this PR they are skipped entirely — not built-without-pushing. The PR run proves the chart lint, the Dockerfile lint, and that the workflows parse and schedule.

The real acceptance test only happens after merge:

docker manifest inspect -v ghcr.io/brtkwr/magento-base:php8.2 | grep '"architecture"'

That prints only amd64 for every tag today; two architectures per tag is the bar.

Out of scope (follow-ups)

  • two-inc/magento-docker, which builds FROM ghcr.io/brtkwr/magento:2.4.8 and declares no platforms.
  • two-inc/magento-plugin's Makefile, which pins the amd64-only michielgerritsen/magento-project-community-edition for the local dev shop.

Nothing downstream can go arm64 until these images publish it, so this goes first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GFS4uN8RLpnbeLmvmB2Rbu

Build each platform on its own native runner (ubuntu-latest for amd64,
ubuntu-24.04-arm for arm64), push by digest, then assemble a manifest
list per tag with `docker buildx imagetools create`.

No QEMU: a Magento composer install plus sample data under emulation is
far too slow to be worth it, and arm runners are free on public repos.

Dockerfiles are unchanged — the base is php:8.2-apache plus apt packages
and extensions built from source, and composer comes from the multi-arch
composer:2 image, so nothing was arch-specific.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFS4uN8RLpnbeLmvmB2Rbu
@brtkwr
brtkwr merged commit 5bddb97 into main Sep 18, 2026
8 checks passed
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