Skip to content

feat: macOS ARM64 support for containerized dev environment#4649

Merged
mociarain merged 21 commits intomasterfrom
tuxerrante/dev-env-macos-support
Mar 23, 2026
Merged

feat: macOS ARM64 support for containerized dev environment#4649
mociarain merged 21 commits intomasterfrom
tuxerrante/dev-env-macos-support

Conversation

@tuxerrante
Copy link
Collaborator

@tuxerrante tuxerrante commented Mar 4, 2026

Summary

  • Adds platform-specific compose overrides (docker-compose.dev-env-macos.yml, docker-compose.dev-env-linux.yml) so the containerized dev environment works on both Linux (Podman) and macOS (Docker)
  • Adds an entrypoint script (hack/devtools/dev-env-entrypoint.sh) that auto-detects the runtime: uses the host Podman socket on Linux, or starts podman system service inside the container on macOS
  • Updates Makefile dev-env targets to detect OS, select the correct compose tool and overrides, and default to the public Fedora registry on macOS (no ACR login required)
  • Splits the containerized dev environment docs into separate Linux and macOS guides for clarity
  • Adds localhost/ prefix to the dev-env image name to avoid Docker prompting for a registry
  • Adds sections on running e2e tests on macOS and SSH tunneling for Geneva Actions testing from a Windows VM

Motivation

Running the RP directly on macOS fails because the Podman v5 Go client cannot talk to the Docker socket. The previous docker-compose.yml had Linux/Podman-specific config (userns_mode: keep-id, host Podman socket mount) that doesn't work on macOS. This change runs Podman natively inside the aro-dev-env container, sidestepping the incompatibility.

Changes

Container runtime

  • macOS override: privileged mode, no SELinux labels, no host socket mount
  • Linux override: mounts the host Podman socket into the container
  • Entrypoint detects the runtime by checking if the host Podman socket was bind-mounted (not via uname, which always returns Linux inside the container)
  • localhost/ prefix on the image name prevents Docker from prompting for a registry selection
  • Removed recursive chown -R aro-dev:aro-dev /workspace — At runtime /workspace is always bind-mounted from the host, so the image layer is hidden and the chown was redundant. It also produced a large, slow layer (duplicating go.mod, .bingo/, etc.). Only /run/podman is chowned (needed for in-container Podman on macOS). Bind-mounted volumes in docker-compose.yml and the platform overrides suffice for permissions; no extra ownership changes required.
  • Fedora base: use public registry on ARM64 (no private image for arm64).
  • Podman service management: Entrypoint starts podman system service inside the container when no host socket is found (macOS). Improved signal handling so the RP and Podman both receive termination signals on container shutdown; shell stays as PID 1 and runs an EXIT trap to clean up.
  • Non-root user: Container runs as aro-dev (matching host UID via USERID build arg). Volume mounts for ~/.azure, ~/.ssh, and /workspace work with bind mounts; Linux override uses userns_mode: keep-id.
  • Go cache: GOCACHE and GOMODCACHE point under /workspace/.cache/ so cache persists across container restarts via the bind-mounted workspace.
  • Image name: Dev-env image uses localhost/aro-rp_aro-dev; docs and commands updated for removal with localhost/ prefix.

Documentation

  • Split containerized-dev-environment.md into a landing page + two platform-specific guides:
    • containerized-dev-environment-linux.md
    • containerized-dev-environment-macos.md
  • macOS guide includes: ARM64 platform config, e2e testing, VPN for private clusters, SSH tunnel for Geneva Actions testing from a Windows VM
  • Removed OrbStack as recommended option (enterprise license concerns)
  • Mount paths for Azure CLI and SSH keys corrected in the containerized dev environment docs.
  • Image removal commands updated to include localhost/ prefix.

Build & config

  • Makefile uses := (simply-expanded) for dev-env variables
  • env.example: bridges CLUSTER and CLUSTER_NAME
  • Dockerfile: added jq, sorted packages, -l flag on useradd

Test plan

  • macOS (ARM64): make dev-env-build builds image with registry.fedoraproject.org, PLATFORM=linux/arm64
  • macOS (ARM64): make dev-env-start starts container, entrypoint auto-starts Podman, RP compiles
  • macOS (ARM64): podman version inside container confirms Podman running on linux/arm64
  • macOS (ARM64): make dev-env-stop cleanly stops container
  • macOS (ARM64): No registry selection prompt on docker compose up
  • Linux (Podman): make dev-env-start uses host Podman socket as before

Copy link
Collaborator

@rh-returners rh-returners left a comment

Choose a reason for hiding this comment

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

tested locally on my Fedora and it still works.

@aasserzo
Copy link
Collaborator

aasserzo commented Mar 9, 2026

Due to the diversion between Linux and MacOS setup instructions, consider splitting into two docs for clarity and maintainability.

@aasserzo
Copy link
Collaborator

I'm seeing a new issue - whenever I run make dev-env-stop; make dev-env-start, all Go dependencies are being re-downloaded. Go cache doesn't seem to work. I wonder if it's happening due to the removal of userns_mode: keep-id and the creation of a new user.

@aasserzo
Copy link
Collaborator

I'm seeing a new issue - whenever I run make dev-env-stop; make dev-env-start, all Go dependencies are being re-downloaded. Go cache doesn't seem to work. I wonder if it's happening due to the removal of userns_mode: keep-id and the creation of a new user.

I tested this, and indeed when userns_mode: keep-id is set, and the useradd section is removed from the Dockerfile, the go cache that already exists in the workspace is used. The workspace is already mounted and the cache is there, so even if you rebuild the image it persists.

To fix this, we can either go back to the "old way", perhaps having separate Dockerfiles per platform, or we can explicitly mount the local go cache into the container like so:

environment:
  GOMODCACHE: /workspace/.gomodcache
  GOCACHE: /workspace/.cache/go-build

Copilot AI review requested due to automatic review settings March 13, 2026 08:59
@github-actions
Copy link

Please rebase pull request.

tuxerrante and others added 21 commits March 20, 2026 17:52
The dev environment previously required Linux with Podman due to
userns_mode: keep-id and a host Podman socket mount. This adds
platform-specific compose overrides and an entrypoint script that
auto-starts Podman inside the container when no host socket is
available, enabling macOS users (OrbStack/Docker) to use the same
`make dev-env-start` workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensures cluster names (AZURE_PREFIX, CLUSTER_NAME, etc.) follow a
consistent format by deriving USER from `git config user.name` when
the shell variable is not already set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skip lastlog/faillog updates which can create large sparse files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Avoid re-evaluating $(shell ...) on every reference by using := instead of =.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the default socket location for both Linux (host-mounted) and
macOS (in-container) paths, simplifying the entrypoint logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Overriding $USER can break tools that depend on the system-provided value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hack/cluster (Go) reads CLUSTER via mapstructure, while
hack/setup_resources.sh and az aro CLI use CLUSTER_NAME.
Setting CLUSTER=${CLUSTER_NAME} prevents confusing errors
when running `go run ./hack/cluster create`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the single doc into platform-specific guides for easier
navigation. The original file becomes a landing page linking to both.
Removes OrbStack recommendation due to enterprise license concerns.
Explain why uname -s cannot be used inside the container and how
the Podman socket check is the correct detection mechanism.
Without the prefix, docker compose prompts the user to select a
registry when the image is not found locally.
Set GOCACHE and GOMODCACHE to paths under /workspace so the Go build
and module caches survive stop/start cycles via the bind mount.
…tion

Add necessary volume mounts for Azure and SSH configurations in the Linux development environment. Disable security labels for improved compatibility with local development setups.
The Dockerfile created an aro-dev user but never switched to it,
so the container still ran as root and wrote root-owned files into
the bind-mounted workspace. Add USER aro-dev, mount credentials
into /home/aro-dev/ instead of /root/, restore userns_mode: keep-id
on Linux for correct UID mapping, and handle /run/podman ownership
for the non-root entrypoint.

Made-with: Cursor
Add a trap to clean up the background Podman service on exit, and
exec the final make command so it becomes PID 1 and receives
SIGTERM directly during container shutdown.

Made-with: Cursor
Changed the image removal commands in the Linux and macOS documentation to use the localhost prefix for consistency and to avoid registry prompts when the image is not found locally.
…ev environment documentation

Changed the documentation to reflect the correct mount paths for the Azure CLI and SSH keys, ensuring they are now directed to the non-root user's home directory instead of the root directory.
make dev-env-build unexpectedly depend on prior Docker ACR credentials and fail for users who have RP_IMAGE_ACR set in their env.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Refactor the dev-env entrypoint script to improve the handling of the Podman service. The script now starts the Podman service inside the container if no host socket is found, while ensuring proper signal handling for both the Podman service and the running application. This change allows the application to receive termination signals directly during container shutdown.
…v-env

Eliminated the unnecessary ownership change for the /workspace directory during the user creation process in the development environment Dockerfile, streamlining the setup.
Refactor the cleanup function in the dev-env entrypoint script to ensure proper termination of both the Podman service and the running application. This enhancement allows for more reliable resource management during container shutdown by explicitly waiting for background processes to exit.
Copilot AI review requested due to automatic review settings March 20, 2026 16:54
@tuxerrante tuxerrante force-pushed the tuxerrante/dev-env-macos-support branch from c1dacbf to 4262558 Compare March 20, 2026 16:54
@tuxerrante tuxerrante removed the needs-rebase branch needs a rebase label Mar 20, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds macOS (ARM64) support for the containerized dev environment by splitting Compose configuration and docs per-platform, and introducing an entrypoint that selects between using a host Podman socket (Linux) vs running Podman inside the container (macOS).

Changes:

  • Add platform-specific docker-compose override files and update base compose to be platform-neutral.
  • Add a dev-env entrypoint script that starts/uses Podman appropriately and launches make runlocal-rp.
  • Split containerized dev environment docs into Linux and macOS guides; update env example for CLUSTER bridging and macOS ARM64 env hints.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
hack/devtools/dev-env-entrypoint.sh New entrypoint to detect host socket vs start in-container Podman, then run RP.
env.example Adds CLUSTER export and commented macOS ARM64/Fedora registry hints.
docs/containerized-dev-environment.md Converts into landing page pointing to Linux/macOS guides; updates mount paths.
docs/containerized-dev-environment-linux.md New Linux-specific setup and usage guide.
docs/containerized-dev-environment-macos.md New macOS/ARM64 guide including e2e and SSH tunneling notes.
docker-compose.yml Makes base compose portable; moves volumes/SELinux bits into overrides; adds entrypoint command & Go cache env.
docker-compose.dev-env-linux.yml Linux override: socket mount, SELinux labels, userns keep-id, label disable opt.
docker-compose.dev-env-macos.yml macOS override: privileged and required volume mounts.
Makefile Adds OS-aware compose selection and registry defaults for dev-env targets.
Dockerfile.dev-env Adds jq, reorders packages, and creates non-root aro-dev user with configurable UID.
.gitignore Adjusts .cache ignore to directory form .cache/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mociarain mociarain merged commit a8959fc into master Mar 23, 2026
35 checks passed
@mociarain mociarain deleted the tuxerrante/dev-env-macos-support branch March 23, 2026 10:29
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.

6 participants