Skip to content

👷(docker) add arm64 platform support for image builds#296

Open
StephanMeijer wants to merge 1 commit into
suitenumerique:mainfrom
StephanMeijer:feature/docker-arm64
Open

👷(docker) add arm64 platform support for image builds#296
StephanMeijer wants to merge 1 commit into
suitenumerique:mainfrom
StephanMeijer:feature/docker-arm64

Conversation

@StephanMeijer
Copy link
Copy Markdown

@StephanMeijer StephanMeijer commented Feb 19, 2026

Purpose / Proposal

Adding support for linux/arm64 when building Docker images.

This is important because:

  1. It enables to run La Suite on devices like the Raspberry Pi and Mac Mini. It will also make it easier for developers to contribute, as many are using Apple MacBooks with arm64 chips.
  2. More and more providers (such as Hetzner) for infrastructure are offering arm64 support.
  3. Sustainability is a point of interest (and sometimes condition) for organizations, commercially but specifically also governments, when they are buying infrastructure.

External contributions

  • I have read and followed the contributing guidelines
  • I have read and agreed to the Code of Conduct
  • I have signed off my commits with git commit --signoff (DCO compliance)
  • I have signed my commits with my SSH or GPG key (git commit -S)
  • My commit messages follow the required format: <gitmoji>(type) title description
  • I have added a changelog entry under ## [Unreleased] section (if noticeable change)
  • I have added corresponding tests for new features or bug fixes (if applicable)

Testing happens when GitHub Workflows are being executed.

Summary by CodeRabbit

  • New Features

    • Docker images now support both AMD64 and ARM64 architectures, enabling deployment on Apple Silicon and ARM-based servers.
  • Chores

    • CI/CD pipeline and changelog updated to enable multi-architecture Docker builds and publishing.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 19, 2026

Walkthrough

Adds QEMU setup and multi-architecture (linux/amd64, linux/arm64) build targets to the GitHub Actions Docker build/push workflow for backend and frontend; updates CHANGELOG to note arm64 support.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
\.github/workflows/docker-hub.yml
Inserted docker/setup-qemu-action@v3 step and enabled multi-arch build platforms (linux/amd64,linux/arm64) in backend and frontend production build-push steps.
Changelog
CHANGELOG.md
Added entry documenting arm64 platform support for Docker image builds.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer (push)
    participant GH as GitHub Actions
    participant QEMU as docker/setup-qemu-action
    participant Buildx as docker buildx
    participant Registry as Docker Registry

    Dev->>GH: push event triggers workflow
    GH->>QEMU: run QEMU setup step
    GH->>Buildx: run build-push with platforms linux/amd64,linux/arm64
    Buildx->>Registry: build and push multi-arch images
    Registry-->>Dev: images available
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically communicates the main change: adding arm64 platform support for Docker image builds, which is the core objective of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Feb 19, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm svgo is 91.0% likely obfuscated

Confidence: 0.91

Location: Package overview

From: ?npm/@svgr/webpack@8.1.0npm/svgo@3.3.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/svgo@3.3.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/docker-hub.yml (1)

46-62: ⚠️ Potential issue | 🟠 Major

The arm64 image is published without being security-scanned.

The Run trivy scan step builds and scans only the default amd64 variant (no --platform flag, running on an ubuntu-latest / amd64 runner). The subsequent Build and push step then publishes both linux/amd64 and linux/arm64 to DockerHub, so the arm64 image bypasses the vulnerability scan entirely.

Because the host is AMD64, arm64 images built locally or via QEMU emulation cannot automatically be found or loaded for scanning by tooling like Trivy without additional steps.

To close this gap, consider one of:

  1. Scan per-platform via matrix — build each platform separately, save as a tarball artifact, load and scan each, then merge manifests on push.
  2. Scan the pushed multi-arch manifest from the registry — push to a staging/short-lived tag first, then run trivy against that remote image with an explicit --platform linux/arm64 flag, before promoting the final tags.

Also applies to: 90-108

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docker-hub.yml around lines 46 - 62, The Trivy scan step
("Run trivy scan" using numerique-gouv/action-trivy-cache) only scans the
default amd64 build while the "Build and push" step
(docker/build-push-action@v6) publishes both linux/amd64 and linux/arm64,
leaving arm64 unscanned; fix by either (A) converting the workflow to a build
matrix over platforms (linux/amd64, linux/arm64) where each matrix job builds
the platform-target (use docker/build-push-action to build and save a tar
artifact), then in each job load that tar and run Trivy with the explicit
--platform flag to scan the platform-specific image before pushing, or (B)
change the push flow to first push to a staging tag (in "Build and push"), then
add a separate scan job that runs Trivy against the remote manifest for each
platform using --platform linux/arm64 and --platform linux/amd64 (promote tags
only after both scans pass); update the "Run trivy scan" and "Build and push"
steps to implement one of these flows so every published platform is scanned.
🧹 Nitpick comments (2)
.github/workflows/docker-hub.yml (2)

26-28: Consider scoping QEMU to only the required platform.

The platforms input for docker/setup-qemu-action@v3 defaults to all, which installs QEMU binaries for every supported architecture. Since the runner already handles linux/amd64 natively, only linux/arm64 emulation is actually needed here.

♻️ Proposed change (apply identically to both jobs)
-      -
-        name: Set up QEMU
-        uses: docker/setup-qemu-action@v3
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+        with:
+          platforms: arm64

Also applies to: 70-72

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docker-hub.yml around lines 26 - 28, The QEMU setup step
using docker/setup-qemu-action@v3 currently installs all architectures; restrict
the action by adding the platforms input to only emulate linux/arm64 (since
linux/amd64 is native) so update the step that references
docker/setup-qemu-action@v3 to include platforms: linux/arm64 (apply the same
change for the other identical job where the step appears).

58-58: Consider using native arm64 runners to reduce QEMU emulation overhead.

The platforms are specified correctly. However, building multiple platforms on the same runner with QEMU can significantly extend build times, particularly for complex Dockerfiles. By distributing platform-specific builds across multiple runners using a matrix strategy, you can drastically reduce build durations and streamline your CI pipeline.

Docker's own CI guidance recommends pairing linux/amd64 with ubuntu-latest and linux/arm64 with ubuntu-24.04-arm in a build matrix, which avoids QEMU emulation entirely for arm64.

This is a good-to-have improvement given that the QEMU approach is functionally correct, but worth considering as build times grow with the project.

Also applies to: 103-103

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docker-hub.yml at line 58, The current platforms:
linux/amd64,linux/arm64 entry causes QEMU emulation overhead; change the
workflow to use a build matrix that creates separate jobs for each platform
(e.g., matrix.os/arch pairs) so arm64 builds run on a native runner and amd64 on
ubuntu-latest; specifically, replace the single platforms field usage with a
matrix strategy that pairs linux/amd64 -> ubuntu-latest and linux/arm64 ->
ubuntu-24.04-arm, then use the matrix values in the job runner and docker buildx
invocation to avoid emulation and significantly reduce build time.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/docker-hub.yml:
- Around line 46-62: The Trivy scan step ("Run trivy scan" using
numerique-gouv/action-trivy-cache) only scans the default amd64 build while the
"Build and push" step (docker/build-push-action@v6) publishes both linux/amd64
and linux/arm64, leaving arm64 unscanned; fix by either (A) converting the
workflow to a build matrix over platforms (linux/amd64, linux/arm64) where each
matrix job builds the platform-target (use docker/build-push-action to build and
save a tar artifact), then in each job load that tar and run Trivy with the
explicit --platform flag to scan the platform-specific image before pushing, or
(B) change the push flow to first push to a staging tag (in "Build and push"),
then add a separate scan job that runs Trivy against the remote manifest for
each platform using --platform linux/arm64 and --platform linux/amd64 (promote
tags only after both scans pass); update the "Run trivy scan" and "Build and
push" steps to implement one of these flows so every published platform is
scanned.

---

Nitpick comments:
In @.github/workflows/docker-hub.yml:
- Around line 26-28: The QEMU setup step using docker/setup-qemu-action@v3
currently installs all architectures; restrict the action by adding the
platforms input to only emulate linux/arm64 (since linux/amd64 is native) so
update the step that references docker/setup-qemu-action@v3 to include
platforms: linux/arm64 (apply the same change for the other identical job where
the step appears).
- Line 58: The current platforms: linux/amd64,linux/arm64 entry causes QEMU
emulation overhead; change the workflow to use a build matrix that creates
separate jobs for each platform (e.g., matrix.os/arch pairs) so arm64 builds run
on a native runner and amd64 on ubuntu-latest; specifically, replace the single
platforms field usage with a matrix strategy that pairs linux/amd64 ->
ubuntu-latest and linux/arm64 -> ubuntu-24.04-arm, then use the matrix values in
the job runner and docker buildx invocation to avoid emulation and significantly
reduce build time.

@StephanMeijer
Copy link
Copy Markdown
Author

StephanMeijer commented Feb 19, 2026

Some executions of CI steps could show an error.

The actions docker/setup-qemu-action@v3 and docker/setup-buildx-action@v3 are not allowed in suitenumerique/people because all actions must be from a repository owned by suitenumerique, created by GitHub, or match one of the patterns: actions/cache@v4, actions/checkout@v4, actions/deploy-pages@*, actions/setup-node@v4, actions/setup-python@v3, actions/setup-python@v5, actions/setup-python@v6, actions/upload-artifact@v4, aquasecurity/setup-trivy@v0.2.2, aquasecurity/trivy-action@0.29.0, astral-sh/setup-uv@v6, azure/setup-helm@v4, crowdin/github-action@v2, docker/build-push-action@v6, docker/login-action@v3, docker/metadata-action@v5, jsdaniell/create-json@v1.2.3, numerique-gouv/action-argocd-webhook-notification@main, numerique-gouv/action-trivy-cache@main, numerique-gouv/helm-gh-pages@add-overwrite-option, peter-evans/create-pull-request@v7.

The allowed actions list is configured in the organization's GitHub Settings. As I am an external contributor, I do not have access to modify these. I request the reviewer of this pull request to contact one of the people in this list: https://github.com/orgs/suitenumerique/people

This pull request introduces QEMU (for emulation) and buildx (for cross-platform docker builds). These are needed because GitHub Actions runners are linux/amd64. To build Docker images for linux/arm64 on an amd64 runner:

  1. QEMU (docker/setup-qemu-action) provides CPU emulation so the runner can execute arm64 instructions
  2. Buildx (docker/setup-buildx-action) extends Docker with multi-platform build support, using QEMU under the hood

Without these, the platforms: linux/amd64,linux/arm64 parameter on docker/build-push-action would fail. Therefore docker/setup-qemu-action@v3 and docker/setup-buildx-action@v3 should be whitelisted on organizational level before merging this pull request.

You can read more about it on github.com/docker/build-push-action.

Signed-off-by: Stephan Meijer <me@stephanmeijer.com>
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/docker-hub.yml (1)

54-62: QEMU emulation will significantly inflate build times; consider adding layer cache

The arm64 portion of the build is emulated using QEMU, and benchmarks have recorded up to 30× speedups when building on native Arm machines versus emulating via QEMU in CI. Neither build-and-push-backend nor build-and-push-frontend configures cache-from/cache-to, so every run pays the full emulated build cost from scratch.

Two recommended mitigations (either or both):

Option A — Add GHA layer cache to the existing build-push steps:

⚡ Add build cache
        name: Build and push
        if: always()
        uses: docker/build-push-action@v6
        with:
          context: .
          target: backend-production
          platforms: linux/amd64,linux/arm64
          build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
+         cache-from: type=gha
+         cache-to: type=gha,mode=max

Apply the same diff to the frontend Build and push step.

Option B — Use a native ubuntu-24.04-arm runner via a matrix strategy to eliminate emulation overhead entirely, building each platform on its native runner and pushing by digest before merging the manifest.

Also applies to: 96-108

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docker-hub.yml around lines 54 - 62, CI currently emulates
arm64 which inflates build time; update the docker/build-push-action@v6 steps
(the build-and-push-backend and build-and-push-frontend steps) to enable layer
caching by adding cache-from and cache-to parameters (e.g., use type=gha and/or
registry cache entries) so builds reuse prior layers, or replace the single-run
approach with a matrix that targets native runners (include an ubuntu-24.04-arm
runner in the matrix) to build the arm64 image natively and then push by digest;
modify the action inputs for the steps that use context/target/platforms to
include cache-from/cache-to or switch to a matrix strategy accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/docker-hub.yml:
- Line 58: The Trivy scan steps use numerique-gouv/action-trivy-cache with
docker-build-args but do not pass a --platform flag, so only linux/amd64 is
scanned while the workflow publishes a multi-arch manifest (platforms:
linux/amd64,linux/arm64); update the Trivy scan steps (the action usages of
numerique-gouv/action-trivy-cache and the docker-build-args inputs) to add a
second scan invocation that passes "--platform=linux/arm64" (or otherwise
include "--platform linux/arm64" in docker-build-args) so the arm64 image layers
are built and scanned, and if that action does not support platform builds, add
a short documented note in the workflow and open a follow-up issue to track
scanning arm64 separately.

---

Nitpick comments:
In @.github/workflows/docker-hub.yml:
- Around line 54-62: CI currently emulates arm64 which inflates build time;
update the docker/build-push-action@v6 steps (the build-and-push-backend and
build-and-push-frontend steps) to enable layer caching by adding cache-from and
cache-to parameters (e.g., use type=gha and/or registry cache entries) so builds
reuse prior layers, or replace the single-run approach with a matrix that
targets native runners (include an ubuntu-24.04-arm runner in the matrix) to
build the arm64 image natively and then push by digest; modify the action inputs
for the steps that use context/target/platforms to include cache-from/cache-to
or switch to a matrix strategy accordingly.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff0f3dc and a3d7c02.

📒 Files selected for processing (2)
  • .github/workflows/docker-hub.yml
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

with:
context: .
target: backend-production
platforms: linux/amd64,linux/arm64
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

arm64 images are never scanned for vulnerabilities

The Trivy scan steps (lines 46–50 and 90–94) pass docker-build-args without a --platform flag, so numerique-gouv/action-trivy-cache only builds and scans the native linux/amd64 image. After this PR, the published multi-arch manifest also includes an linux/arm64 image whose base layers and packages are entirely unscanned — a different binary set that may carry different CVEs.

Options to address:

  1. Add a second scan invocation explicitly targeting linux/arm64 (if the custom action supports --platform linux/arm64 in docker-build-args).
  2. If option 1 is not feasible, document the known gap and open a follow-up issue to track it.

Also applies to: 103-103

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docker-hub.yml at line 58, The Trivy scan steps use
numerique-gouv/action-trivy-cache with docker-build-args but do not pass a
--platform flag, so only linux/amd64 is scanned while the workflow publishes a
multi-arch manifest (platforms: linux/amd64,linux/arm64); update the Trivy scan
steps (the action usages of numerique-gouv/action-trivy-cache and the
docker-build-args inputs) to add a second scan invocation that passes
"--platform=linux/arm64" (or otherwise include "--platform linux/arm64" in
docker-build-args) so the arm64 image layers are built and scanned, and if that
action does not support platform builds, add a short documented note in the
workflow and open a follow-up issue to track scanning arm64 separately.

@StephanMeijer
Copy link
Copy Markdown
Author

Rebased this branch on the latest target branch and force-pushed.

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