Skip to content

feat: replace Docker with Apple Container (macOS 26+ only) #52

Description

@h1d3mun3

Overview

Replace the Docker-based sandbox layer in augur with Apple's official container runtime apple/container. Target: macOS 26 (Tahoe) and later only — macOS 15 support is explicitly out of scope (see rationale below). The Docker mode can remain for Linux users as a separate path.

Background Research

The following is based on a deep research pass conducted in June 2026 (97 agents, 15 primary sources, 25 adversarially verified claims).

Apple Container Architecture

  • Runs a separate lightweight Linux VM per container (Apple Virtualization.framework + vmnet) — not kernel namespaces
  • Network isolation strength is equivalent to Docker's, despite the different model
  • Runs OCI images (Linux containers) natively → existing Dockerfile can be reused as-is
  • macOS-only (no Linux host support)

Why Drop macOS 15

The vmnet framework on macOS 15 cannot support container-to-container communication at all. container network create, --network, and --internal are macOS 26-only features (landed in PR #243). The Apple project explicitly states it has "no plan to address issues found with macOS 15 that cannot be reproduced on macOS 26."

What Works (High Confidence)

Docker feature Apple Container equivalent Source
docker network create --internal container network create --internal command-reference.md; confirmed by automated tests
docker run --network foo container run --network foo Same
--cap-drop NET_ADMIN --cap-drop NET_ADMIN Added in v0.12.0 (2026-04-27)
-v bind mounts, -e env vars Same syntax
Sidecar proxy topology Works Apple contributor jglogan explicitly described and endorsed the pattern in discussion #1170; jamesmacaulay confirmed it with Squid

Gaps That Need Addressing

1. No container network connect (impact: high)

There is no command to attach a running container to a network after start. The current start_sidecar (augur:730) does:

docker run -d --name "$name" --network "$(egress_network_name)" ...
docker network connect bridge "$name"   # ← not available

Fix: Specify both networks at container startup:

container run -d --name "$name" \
    --network "$(egress_network_name)" \
    --network default \
    ...

Also need to confirm whether --subnet/--ip are supported. If not, the startup sequence must change: start sidecar → container inspect to get its IP → start agent container with that IP as HTTPS_PROXY. Small change (~5 lines).

2. No --dns flag (impact: low — effectively a non-issue)

There is no equivalent to --dns 192.0.2.1 --dns-search . (augur:928). However, DNS resolution is reportedly broken inside --internal networks by default (discussion #1170), which means external DNS already fails closed. The DNS self-test in verify_egress_locked (augur:752) should pass as-is. Fix: just delete the two --dns lines.

3. Host gateway reachable from --internal networks (impact: medium — security)

The host gateway IP (e.g. 192.168.128.1) remains reachable from --internal networks, creating a bypass path to any host service bound to 0.0.0.0. Confirmed by multiple community members (discussion #719).

Fix: Add a pf rule on the host:

block in quick from <container-subnet> to <host-gw>

Note: block out direction does not work for vmnet-bridged traffic — only block in is effective (confirmed by tomchuk and gcotone in the same thread). A container system pf subcommand draft exists (issue #1320) but is not yet merged.

This is the only change that requires sudo — the current Docker mode runs entirely without root.

What Does Not Need to Change

  • Dockerfile: already a Linux container, reusable as-is
  • ensure_linux_proxy: container run --rm -v ... swift build works the same way
  • augur-proxy binary itself: no changes needed
  • verify_egress_locked logic: swap docker execcontainer exec; all three probes (proxy reachable, direct connection fails, DNS fails) should still pass

Implementation Plan

Scope

  • In scope: macOS 26 (Tahoe) and later
  • Out of scope: macOS 15, Linux hosts (keep Docker mode, or handle in a separate issue)
  • augur --macos (augur-vm) continues to coexist as a separate mode

Tasks

  1. Mechanical CLI rename (~40 occurrences)

    Docker Apple Container
    docker build container build
    docker run container run
    docker exec container exec
    docker ps container list
    docker rm -f container delete
    docker network rm container network delete
    docker image inspect container image inspect
    docker info container system info (needs verification)
  2. Refactor start_sidecar (~5–20 lines)

    • Remove docker network connect
    • Add --network default to container run at startup
    • If --subnet/--ip unsupported: inspect sidecar after start to get IP, then start agent
  3. Remove --dns flags (2 lines)

  4. Add pf rule management (~20 lines)

    • Add rule on augur up
    • Remove rule on augur down
    • Design the sudo UX (warn the user upfront)
  5. Rename require_dockerrequire_container

  6. Update tests

    • tests/10_construct_docker.sh: swap Docker shim for container shim
    • tests/20_docker_live.sh: update for live container CLI

Open Questions (Verify Before Starting)

  • Does container network create support --subnet? Does container run support --ip?
  • What is the exact equivalent of docker info (daemon health check)?
  • How to handle the sudo requirement for pf rules — UX design?
  • Monitor apple/container issue #1320 (container system pf) — if merged, sudo may no longer be needed

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions