Skip to content

[oryx] - Publish Oryx for the host architecture (arm64 support) - #1759

Open
Fairuzan Roslan (fairuzan) wants to merge 3 commits into
devcontainers:mainfrom
fairuzan:oryx-arm64
Open

Fairuzan Roslan (fairuzan) wants to merge 3 commits into
devcontainers:mainfrom
fairuzan:oryx-arm64

Conversation

@fairuzan

Copy link
Copy Markdown

Problem

src/oryx/install.sh always publishes Oryx with -r linux-x64, so on arm64 hosts the feature installs successfully but leaves an x86-64 binary that cannot run:

$ file /usr/local/buildscriptgen/GenerateBuildScript
ELF 64-bit LSB pie executable, x86-64, ..., interpreter /lib64/ld-linux-x86-64.so.2

$ oryx --version
rosetta error: failed to open elf at /lib64/ld-linux-x86-64.so.2

(On native arm64 Linux this shows up as exec format error instead of the Rosetta error from Docker Desktop on Apple silicon.)

This is currently one of the blockers for an arm64 build of mcr.microsoft.com/devcontainers/universal. When I built src/universal natively on arm64, all 10 Oryx-related checks in its test-project/test.sh failed for this reason. See also devcontainers/images#1604.

Changes

  • Map dpkg --print-architecture to the matching .NET runtime identifier (amd64 → linux-x64, arm64 → linux-arm64) and use it for both dotnet publish calls. Unsupported architectures fail early with the same (!) Architecture ... unsupported message the hugo/php/ruby features use.
  • Add an oryx-binary-matches-architecture test that reads the ELF e_machine field of GenerateBuildScript and compares it to uname -m. oryx --version alone can miss a mismatch when QEMU or Rosetta emulation is available.
  • Bump the version from 2.0.2 to 2.0.3.

On amd64 the published runtime identifier is still linux-x64, so the build output there doesn't change.

Testing

devcontainer features test --features oryx --project-folder . run natively on arm64 (Apple silicon, Docker Desktop 29.9.2, aarch64 Linux VM):

================== TEST REPORT ==================
✅ Passed:      'oryx'
✅ Passed:      'install_dotnet_and_oryx'
✅ Passed:      'install_older_dotnet_and_oryx'
✅ Passed:      'install_prev_dotnet_and_oryx'
✅ Passed:      'test_python_project'

including:

🔄 Testing 'Oryx version'
✅  Passed 'Oryx version'!
🔄 Testing 'oryx-binary-matches-architecture'
✅  Passed 'oryx-binary-matches-architecture'!

After the change:

$ file /usr/local/buildscriptgen/GenerateBuildScript
ELF 64-bit LSB pie executable, ARM aarch64, ..., interpreter /lib/ld-linux-aarch64.so.1

I also swapped an arm64 build of Oryx into the universal image. oryx --version, oryx build of the Python sample, and oryx prep all work there.

I did not test on amd64 locally. CI on this PR covers that path.

Known limitation (out of scope)

This fixes the Oryx CLI itself. Separately, the SDKs that oryx prep / dynamic install download from https://oryx-cdn.microsoft.io are x86-64 builds regardless of host architecture. On arm64 the downloaded /opt/nodejs/20.11.0/bin/node and /opt/php/8.1.30/bin/php are x86-64 and fail to execute. The existing *-installed-by-oryx checks still pass because they only list /opt/<platform> and don't run the binaries. Fixing that needs arm64 SDK builds on the Oryx side (microsoft/Oryx), so it isn't part of this PR.

The install script always ran `dotnet publish -r linux-x64`, so on arm64
hosts the feature installed an x86-64 GenerateBuildScript binary that
fails to execute ("exec format error", or a Rosetta loader error under
Docker Desktop on Apple silicon).

Map the dpkg architecture to the matching .NET runtime identifier
(amd64 -> linux-x64, arm64 -> linux-arm64) and fail early on anything
else. Add a test that checks the ELF machine type of the published
binary, since emulation can otherwise hide a mismatch.
@fairuzan
Fairuzan Roslan (fairuzan) requested a review from a team as a code owner October 30, 2026 21:37
@fairuzan

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues remain for the architecture-aware Oryx binary publishing changes.

No open issues 🎉

What changed in this PR

Updates the Oryx feature to publish native binaries for amd64 and arm64, addressing the CLI architecture mismatch that blocks arm64 universal images. Downloaded SDK architecture support remains out of scope.

Changes:

  • Selects the .NET runtime identifier from the system architecture for both publish commands and rejects unsupported architectures.
  • Adds an ELF architecture check to detect mismatches even when emulation allows execution.
  • Bumps the feature version to 2.0.3.
File Description
test/​oryx/​test.sh Checks that the Oryx binary’s ELF architecture matches the host.
src/​oryx/​install.sh Publishes both Oryx applications for amd64 or arm64.
src/​oryx/​devcontainer-feature.json Bumps the feature version from 2.0.2 to 2.0.3.

Review effort: Balanced

@v-Kaniska244 Kaniska (v-Kaniska244) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi Fairuzan Roslan (@fairuzan)

Thank you for the contribution. Would you kindly modify this arm64 test workflow as well to include trigger for oryx feature, now that oryx installation should be supported on arm64 systems with this change. Currently that workflow is only triggered for powershell and docker-in-docker features changes.

Add oryx to the paths and change filters of test-pr-arm64.yaml so that
changes to the feature are tested on arm64 runners. Mirror the existing
amd64 matrix exclusions for oryx (ubuntu:jammy and
mcr.microsoft.com/devcontainers/base:ubuntu), which the feature does
not support.
@fairuzan

Fairuzan Roslan (fairuzan) commented Nov 3, 2026 •

Copy link
Copy Markdown
Author

Thanks Kaniska (@v-Kaniska244). I've added oryx to test-pr-arm64.yaml in aaaab7d.

I also excluded oryx from ubuntu:jammy and mcr.microsoft.com/devcontainers/base:ubuntu, same as the amd64 workflow does, since the feature doesn't support those and they'd just fail.

Before pushing I ran the same commands locally on an arm64 machine (Apple silicon). The autogenerated test passes on debian:12, base:debian and base:noble, and all the oryx scenarios pass too. This PR touches src/oryx and test/oryx, so the new arm64 job should kick off here as well.

@v-Kaniska244 Kaniska (v-Kaniska244) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To be further reviewed by maintainers.

Comment thread test/oryx/test.sh Resolved
Replace the raw ELF header read with `file`, which reports the binary's
architecture in readable form. `file` is not present on the base images
used in CI, so install it at the start of the test (with sudo when the
test runs as a non-root user), following the check_packages pattern
used by other feature tests.

This branch has not been deployed

No deployments
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.

4 participants