Build natively on arm64 (Apple Silicon, Asahi)#352
Conversation
The Dockerfile and docker-compose pinned linux/amd64, which forced Rosetta on Apple Silicon and made the build unusable on Linux/aarch64 (e.g. NixOS on Asahi, where no Rosetta exists). Root cause: the upstream Elm 0.19.1 release ships an amd64-only Linux binary, so even on an arm64 host the Elm step segfaulted under emulation. Changes: - Drop the --platform=linux/amd64 pins in Dockerfile (both stages) and docker-compose.yml — the build now follows the host architecture. - Replace the official Elm binary download with @lydell/elm@0.19.1-14, an npm wrapper that ships native binaries for linux_arm64, darwin_arm64, linux_x64, darwin_x64 (and win32_x64) via optionalDependencies. Adds a pnpm.overrides entry so transitively pulled `elm` (via elm-spa, elm-test, elm-review, etc.) resolves to the same multi-arch package. - Add libpq-dev to the builder stage. The libpq node module's node-gyp build needs pg_config; on amd64 prebuilt binaries existed, but on arm64 it falls back to compile-from-source. - Mark elm-coverage as neverBuiltDependencies. Its binwrap installer has no arm64 binary and the package is dev-only, never used by build:docker. - Regenerate pnpm-lock.yaml so the resolution reflects the override. This complements/replaces azimuttapp#314 (open since July 2024 with an arm64 path relying on a third-party Elm image reported broken on Asahi in Jan 2025 by @h3x4d3c1m4l). Refs azimuttapp#295, azimuttapp#311, azimuttapp#314. Verified on macOS arm64: native arm64 image (567MB), `docker compose up` serves Azimutt on :4000, and the BEAM ELF e_machine is AArch64 (`od -An -tx1 -j18 -N2 /app/erts-*/bin/beam.smp` returns `b7 00`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughRemove hardcoded Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
Dockerfile (1)
39-40: ⚡ Quick winAdd
--no-install-recommendsto apt installs.This reduces image bloat and attack surface, and it also resolves the static-analysis findings on these install steps.
Proposed Dockerfile tweak
-RUN apt-get update -y && apt-get install -y build-essential git curl wget libpq-dev && apt-get clean && rm -f /var/lib/apt/lists/*_* +RUN apt-get update -y && apt-get install -y --no-install-recommends build-essential git curl wget libpq-dev && apt-get clean && rm -f /var/lib/apt/lists/*_* -RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y --no-install-recommends nodejs🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile` around lines 39 - 40, The two Dockerfile RUN commands installing packages should include the --no-install-recommends flag to avoid pulling recommended packages; update the first RUN that calls apt-get install -y build-essential git curl wget libpq-dev and the second RUN that installs nodejs after the NodeSource setup to use apt-get install -y --no-install-recommends so image bloat and attack surface are reduced and static-analysis warnings are resolved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@Dockerfile`:
- Around line 39-40: The two Dockerfile RUN commands installing packages should
include the --no-install-recommends flag to avoid pulling recommended packages;
update the first RUN that calls apt-get install -y build-essential git curl wget
libpq-dev and the second RUN that installs nodejs after the NodeSource setup to
use apt-get install -y --no-install-recommends so image bloat and attack surface
are reduced and static-analysis warnings are resolved.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 64f81dfa-d4ab-4050-b4f8-b8c16bc432c0
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
Dockerfiledocker-compose.ymlpackage.json
💤 Files with no reviewable changes (1)
- docker-compose.yml
Per CodeRabbit review on PR azimuttapp#352 — reduces image bloat and attack surface. Adds `ca-certificates` and `gnupg` explicitly: they were previously pulled in via Recommends and are needed by the NodeSource setup_20.x script that runs in the next layer (it imports a GPG key and adds an apt repo over HTTPS). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per CodeRabbit review on PR azimuttapp#352 — reduces image bloat and attack surface. Adds `ca-certificates` and `gnupg` explicitly: they were previously pulled in via Recommends and are needed by the NodeSource setup_20.x script that runs in the next layer (it imports a GPG key and adds an apt repo over HTTPS). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
Dockerfile (1)
39-44: ⚡ Quick winUse
--no-install-recommendson the NodeSource install too.The first apt step already opts out of recommends, but this
nodejsinstall still pulls the default recommendation set. That partially undoes the image-size/attack-surface reduction you just introduced.Proposed fix
-RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y --no-install-recommends nodejs🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile` around lines 39 - 44, The NodeSource installation line currently runs "curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs" which installs recommended packages; update that RUN to pass --no-install-recommends to the apt-get install command for nodejs and preserve the existing cleanup (apt-get clean && rm -f /var/lib/apt/lists/*_*) so the image keeps the reduced size/attack-surface behavior (refer to the RUN that invokes the NodeSource script and the subsequent apt-get install -y nodejs).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@Dockerfile`:
- Around line 39-44: The NodeSource installation line currently runs "curl -fsSL
https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs"
which installs recommended packages; update that RUN to pass
--no-install-recommends to the apt-get install command for nodejs and preserve
the existing cleanup (apt-get clean && rm -f /var/lib/apt/lists/*_*) so the
image keeps the reduced size/attack-surface behavior (refer to the RUN that
invokes the NodeSource script and the subsequent apt-get install -y nodejs).
Why
The Dockerfile and docker-compose pin
--platform=linux/amd64, forcingRosetta on Apple Silicon (slow, segfaults on
mix local.hex, see #295)and making the build unusable on Linux/aarch64 (NixOS/Asahi, where no
Rosetta exists).
Root cause: upstream Elm 0.19.1 only ships an
amd64Linux binary.Removing the platform pin alone is not enough — the Elm download step
fails on arm64.
Approach
Replaces the official Elm binary with
@lydell/elm@0.19.1-14,an npm wrapper maintained by the author of
elm-toolingthat shipsnative binaries for
linux_arm64,darwin_arm64,linux_x64,darwin_x64andwin32_x64viaoptionalDependencies. Same Elm0.19.1 compiler, just packaged with multi-arch support.
A
pnpm.overridesentry redirects the transitively-pulledelmpackage (via
elm-spa,elm-test,elm-review, etc.) to the samemulti-arch package.
Changes
--platform=linux/amd64in both Dockerfile stages anddocker-compose.yml.
wget … binary-for-linux-64-bit.gzwithnpm install -g @lydell/elm@0.19.1-14.pnpm.overrides: { "elm": "npm:@lydell/elm@0.19.1-14" }inpackage.json.libpq-devto the builder stage (thelibpqnode module'snode-gyp build needs
pg_config; on arm64 there's no prebuild).elm-coverageasneverBuiltDependencies: itsbinwrapinstaller has no arm64 binary, and the package is dev-only — never
invoked by
build:docker.pnpm-lock.yamlto reflect the override.Relation to existing work
Refs #295, #311, #314.
This complements/replaces #314 (open since July 2024, approved but never
merged). #314 added a separate
builder_arm64stage relying on athird-party rebuilt-Elm image (
dwayne/elm-for-linux-arm64); thatimage was reported broken on Linux arm64 / Asahi by @h3x4d3c1m4l in
Jan 2025. The approach here uses a single builder stage and an npm
package that is officially packaged by an Elm-tooling maintainer with
explicit support for both
linux_arm64anddarwin_arm64, so it worksidentically on Apple Silicon and Asahi.
Test plan
docker compose up --buildproduces an arm64 image; backend servesAzimutt on
:4000;od -An -tx1 -j18 -N2 /app/erts-*/bin/beam.smpreturns
b7 00(EM_AARCH64), confirming no Rosetta.to a tester for this and will report.
Docker Desktop reproduces Segmentation fault on docker-compose up #295 (BEAM under Rosetta segfaults at
mix local.hex), so the author cannot self-verify amd64 here.Would appreciate a maintainer running
docker compose up --buildon an amd64 host. The diff is no-op for amd64 hosts apart from
swapping the Elm package, and
@lydell/elmships an officiallinux_x64binary.🤖 Generated with Claude Code
Summary by CodeRabbit