Skip to content

fix(ci): build multi-arch wifi-densepose image (linux/arm64 was missing, closes #625)#631

Merged
ruvnet merged 1 commit into
ruvnet:mainfrom
MackDing:fix/docker-arm64-multi-arch
May 19, 2026
Merged

fix(ci): build multi-arch wifi-densepose image (linux/arm64 was missing, closes #625)#631
ruvnet merged 1 commit into
ruvnet:mainfrom
MackDing:fix/docker-arm64-multi-arch

Conversation

@MackDing
Copy link
Copy Markdown

Fixes #625. (Same crash class as the closed-unmerged #136.)

Bug

README.md:44 advertises Docker: multi-arch amd64 + arm64, and PR #547 ("refresh Docker publish") promised multi-arch as part of the :latest rebuild plan, but .github/workflows/sensing-server-docker.yml:100 only sets:

platforms: linux/amd64

So ruvnet/wifi-densepose:latest on Docker Hub today is amd64-only:

$ curl -s https://hub.docker.com/v2/repositories/ruvnet/wifi-densepose/tags/latest/
last_updated: 2026-05-14T17:35:04Z
images:
  arch=amd64    os=linux       size=34509901
  arch=unknown  os=unknown     size=1496      # attestation layer, not arm64

Reproduction (from #625, Mac M3 Pro / macOS Tahoe 26.4.1):

$ docker pull ruvnet/wifi-densepose:latest
Error response from daemon: no matching manifest for linux/arm64/v8 in the
manifest list entries: no match for platform in manifest: not found

Fix

Standard buildx multi-arch recipe — 2 small changes to sensing-server-docker.yml:

Change Why
Add docker/setup-qemu-action@v3 before setup-buildx-action@v3 QEMU user-mode emulation lets the ubuntu-latest (amd64) runner cross-build the linux/arm64 layer. Without it, buildx refuses unknown platforms.
platforms: linux/amd64platforms: linux/amd64,linux/arm64 Actually publish the arm64 layer the README + #547 promised.

docker/Dockerfile.rust needs no changes — verified arch-agnostic:

  • No --target flag on cargo build
  • No target.x86_64-* / target.aarch64-* sections in any Cargo.toml
  • Only native build-deps is cc = "1.0" (already cross-aware)

Smoke tests are unaffected: they docker pull on ubuntu-latest, which auto-selects the amd64 entry from the multi-arch manifest. Multi-arch manifests are transparent to single-arch consumers.

Diff

+11 / -1, one file:

+      - uses: docker/setup-qemu-action@v3
+
       - uses: docker/setup-buildx-action@v3
...
-          platforms: linux/amd64
+          platforms: linux/amd64,linux/arm64

Alternatives considered

  • Native arm64 runner (ubuntu-24.04-arm) instead of QEMU emulation. Faster (~3-5× for a Rust workspace this size) but requires a strategy.matrix over {runs-on, platforms} + a docker/manifest-action join step. ~50 lines of churn vs. 11. Happy to do this in a follow-up if build time on arm64 becomes painful — but the cheap one-line fix unblocks macOS docker issue #625 today.
  • Cross-build with cross / --target aarch64-unknown-linux-gnu in the Dockerfile. Would avoid QEMU runtime emulation but means restructuring the Rust build stage. Bigger blast radius, scope-creep for what is a workflow-config bug.

Scope

Only touches .github/workflows/sensing-server-docker.yml — the workflow #625 is about. nvsim-server-docker.yml:59 has the identical platforms: linux/amd64 bug (different image, separate concern); happy to file a follow-up PR for that one if useful — kept out here for review-clarity.

One observation, not part of this fix

The last 5 runs of sensing-server-docker.yml have failed at the Log in to Docker Hub step (looks like DOCKERHUB_TOKEN rotated/expired). Once that secret-side issue is resolved, the next push to main will produce the first true amd64 + arm64 manifest — and #625 / #136 will close. Pointing this out so the green-CI signal on this PR doesn't get misread as "fix works"; the only way to fully verify the merged behaviour is the post-merge push.

Happy to iterate on commit message, scope, or the QEMU-vs-native-arm-runner question.

…ng, closes ruvnet#625)

PR ruvnet#547 refreshed the sensing-server docker publish and the README badge
advertises 'Docker: multi-arch amd64 + arm64', but
.github/workflows/sensing-server-docker.yml only sets
'platforms: linux/amd64'. The arm64 layer was never actually wired in.

Consequence on Docker Hub today (ruvnet/wifi-densepose:latest, last pushed
2026-05-14 by ruvnet#547):

  $ curl -s https://hub.docker.com/v2/repositories/ruvnet/wifi-densepose/tags/latest/
  images:
    arch=amd64    os=linux
    arch=unknown  os=unknown   # the 1.5KB attestation layer, not arm64

So Apple Silicon Macs (the platform in ruvnet#625) hit:

  docker pull ruvnet/wifi-densepose:latest
  Error: no matching manifest for linux/arm64/v8 in the manifest list

This is the same crash class as the closed-unmerged ruvnet#136 'Docker error on
MacOS'; ruvnet#625 is a fresh report (Mac M3 Pro, macOS Tahoe 26.4.1) of the same
bug.

Fix is the standard buildx multi-arch recipe:

  1. Add docker/setup-qemu-action@v3 before setup-buildx so the amd64 runner
     can cross-build the arm64 layer (QEMU user-mode emulation).
  2. Change 'platforms: linux/amd64' -> 'platforms: linux/amd64,linux/arm64'.

docker/Dockerfile.rust is already arch-agnostic — no '--target' flag, no
amd64-only Cargo deps, only 'cc = "1.0"' which is cross-aware — so no
Dockerfile changes are needed. Buildx + QEMU does the rest.

Smoke tests are unaffected: they 'docker pull' on ubuntu-latest (amd64), so
the runner auto-selects the amd64 entry from the multi-arch manifest.
Multi-arch manifests are transparent to single-arch consumers.

Scope discipline: this PR only touches sensing-server-docker.yml (the file
issue ruvnet#625 is about). nvsim-server-docker.yml has the identical
'platforms: linux/amd64' bug but is out of scope here — happy to file
a follow-up if useful.

Note (not part of this fix): the last 5 runs of this workflow have failed
at the 'Log in to Docker Hub' step (DOCKERHUB_TOKEN secret looks rotated/
expired). That's a separate, secret-side issue I can't touch from a PR.
Once that's resolved, the next push to main will produce a proper
amd64+arm64 manifest for the first time.
Copy link
Copy Markdown
Owner

@ruvnet ruvnet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right diagnosis — README badge advertises arm64 + Apple Silicon users hit no matching manifest for linux/arm64/v8. QEMU setup + linux/amd64,linux/arm64 platforms in buildx is the standard fix and the only thing needed since Dockerfile.rust is arch-agnostic (no --target flag, no platform-specific RUN). Closes #625 + the older #136. Merging.

@ruvnet ruvnet merged commit f54f028 into ruvnet:main May 19, 2026
ruvnet added a commit that referenced this pull request May 25, 2026
Three changes:
1. Dockerfile.rust now builds sensing-server with `--features mqtt`
   (ADR-115 HA-DISCO publisher) and also builds + ships the
   cog-ha-matter binary (ADR-116 Home Assistant + Matter cog with
   mDNS, embedded broker, RuVector-backed thresholds, Ed25519 witness).
   Adds EXPOSE 1883 for the embedded MQTT broker.

2. docker-entrypoint.sh routes `docker run <image> cog-ha-matter ...`
   (or `ha-matter`) to /app/cog-ha-matter, defaulting --sensing-url to
   http://127.0.0.1:3000 so a docker-compose deployment works out of
   the box. The default entrypoint (no first arg) still launches
   sensing-server unchanged.

3. Workflow path filter now also fires on changes to
   v2/crates/wifi-densepose-bfld/** and v2/crates/cog-ha-matter/**
   so future iteration on those crates rebuilds the image.

DOCKERHUB_TOKEN rotated separately (was expired since 2026-05-13,
which is why the last 5 workflow runs failed at the Docker Hub login
step and `latest` on Docker Hub has stayed amd64-only despite #631
being merged). With this commit + rotated token, the next CI run
should land a multi-arch `:latest` with HA-DISCO + cog-ha-matter +
BFLD support.

Reproduced kutayozdur's pull failure on ruv-mac-mini (Apple Silicon,
Darwin arm64) via Tailscale before fixing.

Refs #794, #631, ADR-115, ADR-116, ADR-118.

Co-Authored-By: claude-flow <ruv@ruv.net>
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.

macOS docker issue

2 participants