Sandbox Claude Code and Codex 2026: Docker, gVisor, microVM
For one developer running Claude Code or Codex CLI unattended, a hardened Docker container with default-deny egress covers most of the real risk, and gVisor or a microVM only pays off when you run code you do not control. Docker shares the host kernel, gVisor swaps it for a user-space kernel written in Go, and a microVM such as Firecracker gives each workload its own guest kernel behind KVM. The part people skip is egress: a perfectly isolated container that can reach any host still leaks every file it can read. Both Anthropic and OpenAI say the same thing in their docs, and both tell you to put the permission-bypass flags inside an isolation boundary. Below: the threat model, what the bypass flags remove, one comparison table, a hardened docker run, a compose egress proxy, runsc registration, and the microVM entry points.
TL;DR
- The threat is a prompt-injected shell that reads credentials and sends them out. Kernel escapes are the rarer problem.
- --dangerously-skip-permissions (Claude Code) and --yolo (Codex) remove the prompts. Neither adds isolation, so the container has to.
- Docker hardening (non-root, read-only rootfs, --cap-drop ALL, no-new-privileges, egress allowlist) gets you most of the way.
- gVisor: add it when you want a smaller host-kernel surface and your toolchain survives its syscall gaps. 62 of 352 syscalls are unsupported.
- microVM: add it for multi-tenant agents, CI runners, or untrusted repos. Firecracker advertises under 125 ms boot and under 5 MiB overhead per VM.
- On macOS 26 with Apple silicon, Apple's container tool runs Linux containers as lightweight VMs.
The threat model for an unattended coding agent
An agent that runs for an hour with no human watching has four realistic failure paths, in the order they bite:
1. Prompt-injected shell. A README, issue, web page or dependency postinstall script contains instructions. The model follows them and runs curl or npm publish with your tokens.
2. Exfiltration over egress. Anything the process can read leaves through any open port. Isolation does not help if the network is open.
3. Credential files in $HOME. ~/.ssh, ~/.aws, .env files and the agent's own login token. Anthropic's dev container page warns that with the skip flag a malicious project can exfiltrate anything reachable inside the container, including the credentials in ~/.claude[[2]](#cite-2). OpenAI's Codex docs say the same about Codex credentials[[3]](#cite-3).
4. Docker socket mounts. Mounting /var/run/docker.sock hands the agent the daemon. Docker's security page warns that API access can lead to privilege escalation and shows a bind mount of / as the example[[5]](#cite-5). A container with the socket is not a sandbox.
A kernel exploit comes fifth. It matters for multi-tenant hosting, where the attacker is another customer. For a solo developer on a trusted repo it is the least likely path, which is why a hardened container often suffices.
What the bypass flags actually remove
Both flags remove approval prompts and, in Codex's case, the sandbox too. They are not isolation.
- Claude Code: with --dangerously-skip-permissions, Claude acts without asking. Anthropic says to always run these sessions inside a container, a VM, or the sandbox runtime. The CLI refuses to start with the flag as root[[1]](#cite-1). Admins can block it with permissions.disableBypassPermissionsMode set to "disable" in managed settings[[2]](#cite-2).
- Codex CLI: --dangerously-bypass-approvals-and-sandbox, alias --yolo, means no sandbox and no approvals, flagged "not recommended". The default preset is --sandbox workspace-write --ask-for-approval on-request, with network off unless you set network_access = true under [sandbox_workspace_write][[3]](#cite-3).
Both vendors ship their own host-level sandboxes. Claude Code's built-in Bash sandbox is off by default, enabled with /sandbox, built on the open-source @anthropic-ai/sandbox-runtime, and uses Seatbelt on macOS and bubblewrap plus socat on Linux. It covers shell commands only. File tools, MCP servers and hooks run outside it, so Anthropic says it is not sufficient for fully unattended runs[[1]](#cite-1)[[4]](#cite-4). Codex uses Seatbelt on macOS and bwrap plus seccomp on Linux[[3]](#cite-3). These are useful layers. For unattended work, put the whole process in a container or VM and let the built-in sandbox run inside it. Anthropic notes unprivileged containers need enableWeakerNestedSandbox for that[[4]](#cite-4). For the hosted-agent angle, see [Claude Managed Agents self-hosted sandbox](/blogs/claude-managed-agents-self-hosted-sandbox-mcp-tunnels-enterprise-guide-2026).
Comparison: Docker vs gVisor vs microVM vs Apple container
| Option | What is isolated | Kernel | Startup | OS support | Performance cost | Egress control | Setup effort | Cost |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Docker (runc), hardened | Namespaces, cgroups, capabilities, seccomp (default profile blocks around 44 of 300+ syscalls) | Shared host kernel | No VM boot | Linux native; elsewhere via a Linux VM | Near zero | Your job: internal network plus proxy allowlist | Low | Free |
| gVisor (runsc) | Syscalls handled by the Sentry, a Go user-space kernel | User-space kernel; host kernel sees far fewer calls | Small fixed per-sandbox cost, no numbers published | Linux hosts (install guide is Linux-only) | Low for CPU-bound work; high for syscall-heavy or small-file workloads | Netstack by default; --network=none; experimental proxy mode | Low to medium | Free, open source |
| Firecracker microVM | Whole guest OS behind KVM | Separate guest kernel | Under 125 ms boot (vendor claim) | Linux x86_64 and aarch64 with /dev/kvm | Under 5 MiB overhead per VM (vendor claim) | Guest NIC, you filter at host or tap device | High (kernel, rootfs, networking) | Free, open source |
| Kata Containers | Pod or container inside a lightweight VM | Separate guest kernel | Not stated in README | Linux with virtualization support | VM overhead, hypervisor-dependent | Kubernetes network policy on top | Medium to high | Free, open source |
| Apple container | Linux containers as lightweight VMs | Separate guest kernel | Not published in README | macOS 26, Apple silicon only | VM overhead, no GPU claim made | No documented allowlist feature; use a proxy | Low | Free, Apache-2.0 |
| Docker Sandboxes | MicroVM with its own Docker daemon and workspace sync | Separate guest kernel | Not stated | Per Anthropic: any host with it installed | VM overhead | Network policies in its Security guide | Low | Free standalone product per Anthropic; admin policy is a paid tier |
Docker hardening that gets you most of the way
This is the baseline. Every flag below is documented in Docker's docker run reference[[6]](#cite-6). Run the container as a non-root user, because Claude Code requires that for the skip flag anyway.
docker run --rm -it \
--user 1000:1000 \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=512m \
--tmpfs /home/agent/.cache:rw,nosuid,size=1g \
--cap-drop ALL \
--security-opt no-new-privileges \
--pids-limit 512 \
--memory 4g \
--network agent_net \
-e HTTPS_PROXY=http://proxy:3128 \
-e HTTP_PROXY=http://proxy:3128 \
-v "$PWD":/work \
-w /work \
my-agent-image claude
What each line buys you: --read-only stops the agent persisting malware or editing system files. --cap-drop ALL removes every Linux capability; Docker's default is already an allowlist, and dropping all is stricter[[5]](#cite-5). no-new-privileges blocks setuid escalation. The default seccomp profile stays on unless you disable it, and you can swap in your own with --security-opt seccomp=/path/profile.json[[7]](#cite-7). Mount only the project directory. Never mount ~/.ssh, cloud credential files or the Docker socket. Pass a repo-scoped, short-lived token as an environment variable instead.
The remaining gap is the network. Put the agent on an internal network with no route out, and attach a proxy to both that network and a normal one:
services:
agent:
image: my-agent-image
user: "1000:1000"
read_only: true
cap_drop: [ALL]
security_opt: ["no-new-privileges:true"]
pids_limit: 512
mem_limit: 4g
tmpfs: ["/tmp:rw,noexec,nosuid,size=512m"]
environment:
HTTPS_PROXY: http://proxy:3128
HTTP_PROXY: http://proxy:3128
volumes: ["./:/work"]
working_dir: /work
networks: [agent_net]
proxy:
image: ubuntu/squid
volumes:
- ./squid.conf:/etc/squid/squid.conf:ro
- ./allowed-domains.txt:/etc/squid/allowed-domains.txt:ro
networks: [agent_net, egress]
networks:
agent_net:
internal: true
egress: {}
In squid.conf, the allowlist is three lines: acl allowed dstdomain "/etc/squid/allowed-domains.txt", http_access allow allowed, http_access deny all. Start the domain file with api.anthropic.com or api.openai.com, plus your package registry, and add hosts only when a build fails and you agree it should succeed. Anthropic's dev container uses the same default-deny idea through an iptables script, and says the skip flag should be paired with egress restrictions[[2]](#cite-2). If you would rather not assemble and test this yourself, the [WOWHOW Agent Sandbox Kit](/product/agent-sandbox-kit) ($29) ships the hardened Docker config, a Squid default-deny allowlist and a smoke test that proves the egress rules hold.
The catch: proxy variables only constrain tools that honor them. curl, npm and git over HTTPS do. Raw TCP clients do not, but on an internal: true network they have no route anyway, which is why the internal network does the real enforcement and the proxy only supplies the exception list.
When gVisor (runsc) is worth it
gVisor is an application kernel. Its Sentry implements the Linux interface in Go and, per the docs, does not pass system calls through to the host kernel. A Gofer process mediates file access[[8]](#cite-8). The host kernel sees a handful of calls from the Sentry instead of everything the agent's processes issue, so a kernel bug reachable from a syscall is harder to hit. It runs as an OCI runtime, so Docker treats it as a drop-in. Register it:
sudo /usr/local/bin/runsc install
sudo systemctl reload docker
docker run --rm --runtime=runsc hello-world
runsc install edits Docker's runtime configuration for you[[9]](#cite-9). Install the binary first using gVisor's tarball or apt package. After that, add --runtime=runsc to the hardened docker run above. For no network at all, runsc accepts --network=none, which leaves only a loopback[[11]](#cite-11).
The price is compatibility and speed. gVisor's compatibility table for amd64 covers 352 syscalls: 290 implemented fully or partly, 62 not at all. Unimplemented examples include userfaultfd, perf_event_open (returns no such device), io_uring_register and vmsplice. io_uring and ptrace are only partly supported[[10]](#cite-10). For an agent that runs npm, pytest and git, this rarely bites. It bites profilers, debuggers using perf, and anything built on io_uring. On performance, gVisor's own page says CPU-bound work runs natively while syscall-heavy and small-file, VFS-heavy workloads pay the most, and it recommends the Systrap platform for best performance[[12]](#cite-12). A big node_modules install is exactly the file-heavy case, so time it before you commit.
When a microVM is justified
A microVM gives the workload its own kernel. A guest kernel exploit lands inside the VM, and the attacker still needs a hypervisor escape. Anthropic's sandbox page makes the same call: a dedicated VM is the strongest separation and fits untrusted code or policy that demands kernel-level separation[[4]](#cite-4). Justify it when:
- Several customers or teams share one host (multi-tenant agents).
- You run CI runners that execute pull-request code from strangers.
- You build a Codex-cloud-style service where each task gets a fresh machine.
Firecracker needs read/write access to /dev/kvm on x86_64 or aarch64 Linux and advertises boot under 125 ms and under 5 MiB overhead per VM[[13]](#cite-13). The one-liner, from its getting-started guide, boots from a JSON config holding the kernel and rootfs:
sudo ./firecracker --api-sock /tmp/firecracker.socket --config-file vm-config.json
Building the kernel image, rootfs and tap networking is a project of its own[[14]](#cite-14). Kata Containers wraps a lightweight VM behind a containerd shimv2 runtime so Kubernetes can schedule it like a pod, and kata-runtime check tests whether a host can run it[[15]](#cite-15). Follow the Kata install guide for the runtime-class registration rather than copying a snippet from memory. For a single developer who wants VM isolation without the assembly, Docker Sandboxes (a microVM with its own Docker daemon) is the lower-effort route Anthropic points to[[4]](#cite-4).
Apple container on macOS 26
Apple's open-source container tool runs Linux containers as lightweight virtual machines on a Mac. It needs Apple silicon, supports macOS 26 only, is Apache-2.0, and builds on the Containerization Swift package. Install the signed package from the GitHub releases page, then:
container system start
container run --rm alpine echo hello
The README says the project is under active development, release versions are product versions rather than semantic versions, and experimental features may change[[16]](#cite-16).
Which one to pick
Solo developer, trusted repo, Linux or Mac: hardened Docker plus the egress proxy, then the vendor's built-in sandbox inside it. Running agents you cannot supervise on code you did not write: add --runtime=runsc if your toolchain passes a smoke run, or move to a microVM. Selling agent runs to other people: microVM, no debate. Whichever you choose, cap the money side too, since a contained agent can still burn tokens. See [Claude Code spend limits and Codex runaway bills](/blogs/claude-code-spend-limit-hard-caps-codex-runaway-bill-2026), price a run with the [agent run cost simulator](/tools/agent-run-cost-simulator), and check that the Codex daemon is not leaving state behind in [this disk usage guide](/blogs/codex-cli-daemon-background-process-disk-usage-how-to-turn-off-2026).
Quick answers
Is --dangerously-skip-permissions safe inside Docker?
Safer, not safe. The container limits file and process damage, but Anthropic warns a malicious project can still exfiltrate anything reachable inside it, including Claude credentials. Add egress restrictions, avoid mounting host secrets, and use a non-root user, which the flag requires.
Does Docker isolate the kernel?
No. Containers share the host kernel and rely on namespaces, cgroups, capabilities and seccomp. That is enough against a misbehaving agent and not enough against a determined attacker with a kernel exploit, which is the gap gVisor and microVMs close.
Is gVisor or a microVM stronger?
A microVM, in general, because the boundary is a hypervisor and a separate guest kernel. gVisor shrinks the host kernel surface but still runs on the host kernel. gVisor is easier to adopt because it plugs into Docker as --runtime=runsc.
What does Codex do by default for network access?
It is off. The default preset runs workspace-write with network disabled, and you enable it with network_access = true under [sandbox_workspace_write]. Using --yolo removes the sandbox entirely, so put it inside a container.
Can I use Apple container to sandbox agents on a Mac?
Yes, on Apple silicon with macOS 26. It runs each Linux container as a lightweight VM. It is under active development, so pin the version and test before relying on it for anything unattended.
Sources
1. Claude Code: configure the sandboxed Bash tool (accessed 16 October 2026)
2. Claude Code: development containers (accessed 16 October 2026)
3. OpenAI Codex: agent approvals and security (formerly developers.openai.com/codex, accessed 16 October 2026)
4. Claude Code: choose a sandbox environment (accessed 16 October 2026)
5. Docker Engine security (accessed 16 October 2026)
6. docker container run reference (accessed 16 October 2026)
7. Docker seccomp security profiles (accessed 16 October 2026)
8. gVisor documentation (accessed 16 October 2026)
9. gVisor installation (accessed 16 October 2026)
10. gVisor Linux amd64 syscall compatibility (accessed 16 October 2026)
11. gVisor networking (accessed 16 October 2026)
12. gVisor performance guide (accessed 16 October 2026)
13. Firecracker project site (accessed 16 October 2026)
14. Firecracker getting started (accessed 16 October 2026)
15. Kata Containers repository (accessed 16 October 2026)
16. Apple container repository (accessed 16 October 2026)
Every product mentioned is available at wowhow.cloud — pay once, ship forever.
---
Originally published at wowhow.cloud
Mentions
@rizzu26 I'm using Apple Container apple/container
さよなら Docker Desktop : Apple container machine を「Mac 版 WSL」にする TL;DR - Apple 純正の container の container machine で長期稼働する Linux VM を立て、その中で Docker を動かせば Docker Desktop なしで docker compose が動く - ただし container machine にはポート公開(--publish)が無いため、そのままでは localhost で繋がらない - ssh ポートフォワーディングでポートと docker.sock を Mac 側に転送すれば、localhost も Mac の docker コマンドもそのまま使える - 結果として、構成は「ほとんど WSL2」になる :::note 本記事は社内 LT(2026-09)で発表した内容をブログ向けに再構成したものです。 ::: 背景 Mac で docker compose といえば? Mac で docker compose を使うなら、これまでのデファクトスタンダードは Docker Desktop でした。 ただし Docker Desktop は、一定規模以上の企業で利用する場合は有償プランが必要です。 一方で、Apple は Mac 用のコンテナ実行環境として container を OSS で公開しています。 今回はこの Apple 純正の container だけで、Docker Desktop を置き換えられないか試してみました。 Apple container とは Apple container は、Mac 上で Linux を軽量 VM として動かす Apple 謹製のツールです。 使い方は大きく 2 つあります。 | | container run | container machine | | --- | --- | --- | | 位置づけ | コンテナ 1 つ = 専用の軽量 VM | 長期稼働する汎用 Linux VM | | 用途 | docker run のような単発実行 | Ubuntu を入れて apt も docker も使える | どちらも共通して、ホストとは virtiofs でファイルを共有し、VM ごとに専用の IP が振られます。 今回使うのは container machine の方です。 VM の中に Docker Engine を入れてしまえば、普段どおり docker compose が使えるはず……という目論見です。 問題:localhost で繋がらない ところが、ここで壁にぶつかります。 - ポート公開のオプション --publish があるのは container run だけで、container machine には無い - VM の IP(192.168.64.x)を直接叩けば届く。でも localhost ではない - Docker のソケットも VM の中だけ。Mac の docker コマンドからは使えない localhost 以外だと、アプリが壊れる 「IP 直打ちで届くならいいのでは?」と思うかもしれません。 しかし開発用の設定は「アクセス元は localhost」前提になっていることが多く、たとえば以下のような設定に影響が出ます。 - ホスト許可 - Cookie のドメイン - リダイレクト先 URL 実際、私のチームで開発中の Rails + Vite アプリでは、特定のドメインか localhost 以外からの Referer を reject する設定になっており、IP 直打ちではアクセスできませんでした。 /etc/hosts でそのドメインを VM の IP に向ける手もありますが、そうすると今度はアプリ側の設定ファイル等の変更が必要になります。 開発環境のためにアプリの設定をいじるのは本末転倒なので、Mac の localhost でそのまま繋がるようにしたいところです。 解決策:ssh ポートフォワーディング そこで使うのが、昔ながらの ssh ポートフォワーディングです。 mkdir -p ~/.cache/container-machine-compose ssh -f -N \ -L 127.0.0.1:8080:localhost:8080 \ -L ~/.cache/container-machine-compose/devbox-docker.sock:/var/run/docker.sock \ <user>@<VM_IP> この ssh コマンド 1 つで、以下の 2 つのトンネルを張っています。 flowchart LR A["Mac localhost:8080"] -- SSH トンネル --> B["VM 内 :8080 (nginx)"] C["Mac の docker CLI"] -- SSH トンネル --> D["VM 内 docker.sock"] - 1 本目の -L は TCP ポートの転送です。Mac の localhost:8080 へのアクセスが VM 内の :8080 に届きます - 2 本目の -L は Unix ドメインソケットの転送です。Mac 側の ~/.cache/container-machine-compose/devbox-docker.sock が VM 内の /var/run/docker.sock に繋がります - -f でバックグラウンド実行、-N でリモートコマンドを実行せずトンネルだけを張ります VM に sshd と公開鍵を入れておけば、Mac 標準の ssh だけで、localhost と docker コマンドの両方を繋げられる点がポイントです。追加のツールは不要です。 Mac の docker CLI から VM の Docker を使う 転送したソケットを Docker CLI から使うには、docker context を作っておくと便利です。 docker context create cm-devbox \ --docker "host=unix://$HOME/.cache/container-machine-compose/devbox-docker.sock" docker context use cm-devbox これで、Mac で打った docker / docker compose コマンドの向き先が、すべて VM 内の Docker Engine になります。 後述のキットの tunnel.sh では、この context の作成までを自動で行っています。 :::note Mac 側には Docker Desktop ではなく、Docker CLI(と compose プラグイン)だけをインストールしておけば OK です。 ::: 実践:あなたの Mac でも試せる VM の作成からトンネルの張り直しまでをスクリプトにまとめ、サンプルアプリ(nginx + API)付きのキットとして公開しました。 Junm0ri/container-machine-compose 前提 - Apple silicon の Mac(macOS 26) - container CLI がインストール済み - SSH の鍵ペア(~/.ssh/id_ed25519.pub など) - Mac の docker コマンドから使う場合は、Docker CLI(brew install docker docker-compose) 動作確認環境は macOS 26.6.2 / container CLI 1.0.0 です。 一連の流れ キットは、ホームディレクトリ配下の空白を含まないパスに clone してください。 git clone https://github.com/Junm0ri/container-machine-compose.git ~/container-machine-compose cd ~/container-machine-compose ./setup.sh # VM を作成、Docker と SSH 鍵を設定 ./tunnel.sh # ポートと docker.sock を転送 docker context use cm-devbox docker compose up -d # Mac から実行、VM の中で動く open http://localhost:8080 # ホストから VM 内の Web サーバーにアクセス! docker compose up -d は Mac 上で実行していますが、コンテナが動いているのは VM の中です。 そして、ブラウザからは http://localhost:8080 でアクセスできます。 LT のライブデモでも、この流れで VM 内の Web サーバーに localhost からアクセスできることを確認しました。 主なスクリプトの役割は以下のとおりです。 - setup.sh:イメージのビルド → container machine の作成 → VM 内の Docker と SSH の初期設定までを行います。何度実行しても問題ありません - tunnel.sh:Mac の localhost:<port> と Docker ソケットを SSH で VM に転送し、docker context(cm-devbox)も作成します。VM の IP が変わっていれば張り直します。./tunnel.sh stop / ./tunnel.sh status で停止・状態確認もできます 自分のプロジェクトで使う場合は、docker-compose.yml を置き換えて、Mac に転送したいポートを TUNNEL_PORTS に並べてください(例:TUNNEL_PORTS="3000 5173" ./tunnel.sh)。 設定項目やハマりどころ、片付け方法はリポジトリの README にまとめています。 :::note compose.yml で bind mount を使う場合、マウント元のパスは VM から見たパスとして解釈されます。 ホームディレクトリ配下は virtiofs で同じパスのまま共有されているのでそのまま動きますが、ホームの外(/tmp など)は VM から見えないため空になります。 ::: 結果:ほとんど WSL 出来上がった構成を WSL2 と比べてみると、驚くほど似ています。 | | WSL2 | 今回の構成 | | --- | --- | --- | | Linux VM | Hyper-V | container machine | | ファイル共有 | /mnt/c | virtiofs(同一パス) | | localhost | localhostForwarding | SSH トンネル | | 成熟度 | OS 標準機能 | 発展途上・自前管理 | まさに「Mac 版 WSL」と呼べる構成になりました。 注意点 - SSH トンネルは公式機能ではありません - 将来 container machine にポート公開の機能が来れば、不要になるかもしれません - まだあまり深いところまでは触れていません - WSL と同等ではない機能制限があるかもしれません まとめ - Apple 純正ツールだけで docker compose が動く - localhost の壁は ssh ポートフォワーディングで解決 - Mac の docker コマンドもそのまま使える Docker Desktop のライセンスが気になっている方は、ぜひ試してみてください。
さよなら Docker Desktop : Apple container machine を「Mac 版 WSL」にする TL;DR Apple 純正の container の container machine で長期稼働する Linux VM を立て、その中で Docker を動かせば Docker Desktop なしで docker compose が動く ただし container machine にはポート公開(--publish)が無いため、そのままでは localhost で繋がらない ssh ポートフォワーディングでポートと docker.sock を Mac 側に転送すれば、localhost も Mac の docker コマンドもそのまま使える 結果として、構成は「ほとんど WSL2」になる ! 本記事は社内 LT(2026-09)で発表した内容をブログ向けに再構成したものです。 背景 Mac で docker compose といえば? Mac で docker compose を使うなら、これまでのデファクトスタンダードは Docker Desktop でした。 ただし Docker Desktop は、一定規模以上の企業で利用する場合は有償プランが必要です。 一方で、Apple は Mac 用のコンテナ実行環境として container を OSS で公開しています。 今回はこの Apple 純正の container だけで、Docker Desktop を置き換えられないか試してみました。 Apple container とは Apple container は、Mac 上で Linux を軽量 VM として動かす Apple 謹製のツールです。 使い方は大きく 2 つあります。 container run container machine 位置づけ コンテナ 1 つ = 専用の軽量 VM 長期稼働する汎用 Linux VM 用途 docker run のような単発実行 Ubuntu を入れて apt も docker も使える どちらも共通して、ホストとは virtiofs でファイルを共有し、VM ごとに専用の IP が振られます。 今回使うのは container machine の方です。 VM の中に Docker Engine を入れてしまえば、普段どおり docker compose が使えるはず……という目論見です。 問題:localhost で繋がらない ところが、ここで壁にぶつかります。 ポート公開のオプション --publish があるのは container run だけで、container machine には無い VM の IP(192.168.64.x)を直接叩けば届く。でも localhost ではない Docker のソケットも VM の中だけ。Mac の docker コマンドからは使えない localhost 以外だと、アプリが壊れる 「IP 直打ちで届くならいいのでは?」と思うかもしれません。 しかし開発用の設定は「アクセス元は localhost」前提になっていることが多く、たとえば以下のような設定に影響が出ます。 ホスト許可 Cookie のドメイン リダイレクト先 URL 実際、私のチームで開発中の Rails + Vite アプリでは、特定のドメインか localhost 以外からの Referer を reject する設定になっており、IP 直打ちではアクセスできませんでした。 /etc/hosts でそのドメインを VM の IP に向ける手もありますが、そうすると今度はアプリ側の設定ファイル等の変更が必要になります。 開発環境のためにアプリの設定をいじるのは本末転倒なので、Mac の localhost でそのまま繋がるようにしたいところです。 解決策:ssh ポートフォワーディング そこで使うのが、昔ながらの ssh ポートフォワーディングです。 mkdir -p ~/.cache/container-machine-compose ssh -f -N \ -L 127.0.0.1:8080:localhost:8080 \ -L ~/.cache/container-machine-compose/devbox-docker.sock:/var/run/docker.sock \ <user>@<VM_IP> この ssh コマンド 1 つで、以下の 2 つのトンネルを張っています。 1 本目の -L は TCP ポートの転送です。Mac の localhost:8080 へのアクセスが VM 内の :8080 に届きます 2 本目の -L は Unix ドメインソケットの転送です。Mac 側の ~/.cache/container-machine-compose/devbox-docker.sock が VM 内の /var/run/docker.sock に繋がります -f でバックグラウンド実行、-N でリモートコマンドを実行せずトンネルだけを張ります VM に sshd と公開鍵を入れておけば、Mac 標準の ssh だけで、localhost と docker コマンドの両方を繋げられる点がポイントです。追加のツールは不要です。 Mac の docker CLI から VM の Docker を使う 転送したソケットを Docker CLI から使うには、docker context を作っておくと便利です。 docker context create cm-devbox \ --docker "host=unix://$HOME/.cache/container-machine-compose/devbox-docker.sock" docker context use cm-devbox これで、Mac で打った docker / docker compose コマンドの向き先が、すべて VM 内の Docker Engine になります。 後述のキットの tunnel.sh では、この context の作成までを自動で行っています。 ! Mac 側には Docker Desktop ではなく、Docker CLI(と compose プラグイン)だけをインストールしておけば OK です。 実践:あなたの Mac でも試せる VM の作成からトンネルの張り直しまでをスクリプトにまとめ、サンプルアプリ(nginx + API)付きのキットとして公開しました。 Junm0ri/container-machine-compose 前提 Apple silicon の Mac(macOS 26) container CLI がインストール済み SSH の鍵ペア(~/.ssh/id_ed25519.pub など) Mac の docker コマンドから使う場合は、Docker CLI(brew install docker docker-compose) 動作確認環境は macOS 26.6.2 / container CLI 1.0.0 です。 一連の流れ キットは、ホームディレクトリ配下の空白を含まないパスに clone してください。 git clone Junm0ri/container-machine-compose ~/container-machine-compose cd ~/container-machine-compose ./setup.sh # VM を作成、Docker と SSH 鍵を設定 ./tunnel.sh # ポートと docker.sock を転送 docker context use cm-devbox docker compose up -d # Mac から実行、VM の中で動く open localhost # ホストから VM 内の Web サーバーにアクセス! docker compose up -d は Mac 上で実行していますが、コンテナが動いているのは VM の中です。 そして、ブラウザからは localhost でアクセスできます。 LT のライブデモでも、この流れで VM 内の Web サーバーに localhost からアクセスできることを確認しました。 主なスクリプトの役割は以下のとおりです。 setup.sh:イメージのビルド → container machine の作成 → VM 内の Docker と SSH の初期設定までを行います。何度実行しても問題ありません tunnel.sh:Mac の localhost:<port> と Docker ソケットを SSH で VM に転送し、docker context(cm-devbox)も作成します。VM の IP が変わっていれば張り直します。./tunnel.sh stop / ./tunnel.sh status で停止・状態確認もできます 自分のプロジェクトで使う場合は、docker-compose.yml を置き換えて、Mac に転送したいポートを TUNNEL_PORTS に並べてください(例:TUNNEL_PORTS="3000 5173" ./tunnel.sh)。 設定項目やハマりどころ、片付け方法はリポジトリの README にまとめています。 ! compose.yml で bind mount を使う場合、マウント元のパスは VM から見たパスとして解釈されます。 ホームディレクトリ配下は virtiofs で同じパスのまま共有されているのでそのまま動きますが、ホームの外(/tmp など)は VM から見えないため空になります。 結果:ほとんど WSL 出来上がった構成を WSL2 と比べてみると、驚くほど似ています。 WSL2 今回の構成 Linux VM Hyper-V container machine ファイル共有 /mnt/c virtiofs(同一パス) localhost localhostForwarding SSH トンネル 成熟度 OS 標準機能 発展途上・自前管理 まさに「Mac 版 WSL」と呼べる構成になりました。 注意点 SSH トンネルは公式機能ではありません 将来 container machine にポート公開の機能が来れば、不要になるかもしれません まだあまり深いところまでは触れていません WSL と同等ではない機能制限があるかもしれません まとめ Apple 純正ツールだけで docker compose が動く localhost の壁は ssh ポートフォワーディングで解決 Mac の docker コマンドもそのまま使える Docker Desktop のライセンスが気になっている方は、ぜひ試してみてください。
@jobergum "macos containers" -- is this referring to apple/container?
🔥 Топ-3 находки на GitHub ⭐️Используй их, чтобы обогнать 90% людей! 💼Подписывайся на наш телеграм-канал — прямая ссылка в профиле, там ещё больше подобных подборок и не только! 📆Ежедневный контент на тему AI/IT/LLM и многое другое! 1. hydralauncher/hydra 2. apple/container 3. NickvisionApps/Parabolic #github #opensource #нейросети #программирование #IT [en-US] 🔥 Top 3 GitHub Finds ⭐️Use them to outsmart 90% of people! 💼Subscribe to our Telegram channel — direct link in the profile — for even more collections like this and more! 📆Daily content on AI/IT/LLM and much more! 1. hydralauncher/hydra 2. apple/container 3. NickvisionApps/Parabolic #github #opensource #neuralnetworks #programming #IT
container: Create and run Linux containers as lightweight virtual machines on your Mac (51k stars) What it does All text below is quoted directly from the project README. >container is a tool that you can use to create and run Linux containers as lightweight virtual machines on your Mac. It's written in Swift, and optimized for Apple silicon. Next steps: - Take a guided tour of container by building, running, and publishing a simple web server image. - Learn how to use various container features. - Read a brief description and technical overview of container. - Browse the full command reference. - Build and run container on your own development system. - View the project API documentation. >Run your first container: container run --rm alpine echo hello Repository apple/container Repository stats |Metric|Value| |:-|:-| |Stars|50,815| |Forks|1,837| |Last release|1.6.0 (2026-10-20)| |Languages|Swift 98.4%| |Contributors|123| |AI contributor accounts (Claude / Codex / Cursor / Copilot)|claude: 11| |AI co-authored commits|Claude: 5| Main contributor |Field|Value| |:-|:-| |Name|J Logan| |GitHub|@jglogan| |Commits to this repo|223 (top contributor)| |Followers|108| |Public repos|20| |On GitHub since|2011-09-01| ────────────────────────────── 📌 How many great GitHub repos have you discovered and completely forgotten about? Don't let another useful tool disappear into your Reddit feed. Get the community's best repos, organized by category, plus key takeaways from real developer discussions, delivered to your inbox twice a week. 📬 Never lose track of great repos again. Subscribe free.
800 Commits: Watch Apple's Containers Project Evolve in 5 Minutes This video visualizes the entire 1-year history of Apple's `apple/container` GitHub repository using Gource, transforming 800 commits into a vibrant emerald forest. You'll see 120 contributors, including top developers like J Logan, build this Swift-based tool designed for running Linux containers on Macs. Files appear and disappear, branches expand and contract, creating a dynamic visualization of the project's evolution over time. If you love seeing code history unfold like this, hit that subscribe button for more open-source project visualizations! 🔗 Repo: apple/container ⭐ 50,804 stars 🎨 Visualized with Gource 🎵 Music: "4. Жир Жоп ([GT150] Ð /Ð - Ð Ð°Ñ Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ )" by P/N — CC0 — archive.org | "EDG.5.30.2021.1 (Thomas Park- Endless Dub Generation 5.30.2021 [treetrunk 671])" by Thomas Park — Public Domain — archive.org #apple container #gource visualization #open source project #swift programming #github history #linux containers mac #software development #data visualization
@devjuninho Só não tem UI nativa apple/container
Sandbox Claude Code and Codex 2026: Docker, gVisor, microVM For one developer running Claude Code or Codex CLI unattended, a hardened Docker container with default-deny egress covers most of the real risk, and gVisor or a microVM only pays off when you run code you do not control. Docker shares the host kernel, gVisor swaps it for a user-space kernel written in Go, and a microVM such as Firecracker gives each workload its own guest kernel behind KVM. The part people skip is egress: a perfectly isolated container that can reach any host still leaks every file it can read. Both Anthropic and OpenAI say the same thing in their docs, and both tell you to put the permission-bypass flags inside an isolation boundary. Below: the threat model, what the bypass flags remove, one comparison table, a hardened docker run, a compose egress proxy, runsc registration, and the microVM entry points. TL;DR - The threat is a prompt-injected shell that reads credentials and sends them out. Kernel escapes are the rarer problem. - --dangerously-skip-permissions (Claude Code) and --yolo (Codex) remove the prompts. Neither adds isolation, so the container has to. - Docker hardening (non-root, read-only rootfs, --cap-drop ALL, no-new-privileges, egress allowlist) gets you most of the way. - gVisor: add it when you want a smaller host-kernel surface and your toolchain survives its syscall gaps. 62 of 352 syscalls are unsupported. - microVM: add it for multi-tenant agents, CI runners, or untrusted repos. Firecracker advertises under 125 ms boot and under 5 MiB overhead per VM. - On macOS 26 with Apple silicon, Apple's container tool runs Linux containers as lightweight VMs. The threat model for an unattended coding agent An agent that runs for an hour with no human watching has four realistic failure paths, in the order they bite: 1. Prompt-injected shell. A README, issue, web page or dependency postinstall script contains instructions. The model follows them and runs curl or npm publish with your tokens. 2. Exfiltration over egress. Anything the process can read leaves through any open port. Isolation does not help if the network is open. 3. Credential files in $HOME. ~/.ssh, ~/.aws, .env files and the agent's own login token. Anthropic's dev container page warns that with the skip flag a malicious project can exfiltrate anything reachable inside the container, including the credentials in ~/.claude[[2]](#cite-2). OpenAI's Codex docs say the same about Codex credentials[[3]](#cite-3). 4. Docker socket mounts. Mounting /var/run/docker.sock hands the agent the daemon. Docker's security page warns that API access can lead to privilege escalation and shows a bind mount of / as the example[[5]](#cite-5). A container with the socket is not a sandbox. A kernel exploit comes fifth. It matters for multi-tenant hosting, where the attacker is another customer. For a solo developer on a trusted repo it is the least likely path, which is why a hardened container often suffices. What the bypass flags actually remove Both flags remove approval prompts and, in Codex's case, the sandbox too. They are not isolation. - Claude Code: with --dangerously-skip-permissions, Claude acts without asking. Anthropic says to always run these sessions inside a container, a VM, or the sandbox runtime. The CLI refuses to start with the flag as root[[1]](#cite-1). Admins can block it with permissions.disableBypassPermissionsMode set to "disable" in managed settings[[2]](#cite-2). - Codex CLI: --dangerously-bypass-approvals-and-sandbox, alias --yolo, means no sandbox and no approvals, flagged "not recommended". The default preset is --sandbox workspace-write --ask-for-approval on-request, with network off unless you set network_access = true under [sandbox_workspace_write][[3]](#cite-3). Both vendors ship their own host-level sandboxes. Claude Code's built-in Bash sandbox is off by default, enabled with /sandbox, built on the open-source @anthropic-ai/sandbox-runtime, and uses Seatbelt on macOS and bubblewrap plus socat on Linux. It covers shell commands only. File tools, MCP servers and hooks run outside it, so Anthropic says it is not sufficient for fully unattended runs[[1]](#cite-1)[[4]](#cite-4). Codex uses Seatbelt on macOS and bwrap plus seccomp on Linux[[3]](#cite-3). These are useful layers. For unattended work, put the whole process in a container or VM and let the built-in sandbox run inside it. Anthropic notes unprivileged containers need enableWeakerNestedSandbox for that[[4]](#cite-4). For the hosted-agent angle, see [Claude Managed Agents self-hosted sandbox](/blogs/claude-managed-agents-self-hosted-sandbox-mcp-tunnels-enterprise-guide-2026). Comparison: Docker vs gVisor vs microVM vs Apple container | Option | What is isolated | Kernel | Startup | OS support | Performance cost | Egress control | Setup effort | Cost | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Docker (runc), hardened | Namespaces, cgroups, capabilities, seccomp (default profile blocks around 44 of 300+ syscalls) | Shared host kernel | No VM boot | Linux native; elsewhere via a Linux VM | Near zero | Your job: internal network plus proxy allowlist | Low | Free | | gVisor (runsc) | Syscalls handled by the Sentry, a Go user-space kernel | User-space kernel; host kernel sees far fewer calls | Small fixed per-sandbox cost, no numbers published | Linux hosts (install guide is Linux-only) | Low for CPU-bound work; high for syscall-heavy or small-file workloads | Netstack by default; --network=none; experimental proxy mode | Low to medium | Free, open source | | Firecracker microVM | Whole guest OS behind KVM | Separate guest kernel | Under 125 ms boot (vendor claim) | Linux x86_64 and aarch64 with /dev/kvm | Under 5 MiB overhead per VM (vendor claim) | Guest NIC, you filter at host or tap device | High (kernel, rootfs, networking) | Free, open source | | Kata Containers | Pod or container inside a lightweight VM | Separate guest kernel | Not stated in README | Linux with virtualization support | VM overhead, hypervisor-dependent | Kubernetes network policy on top | Medium to high | Free, open source | | Apple container | Linux containers as lightweight VMs | Separate guest kernel | Not published in README | macOS 26, Apple silicon only | VM overhead, no GPU claim made | No documented allowlist feature; use a proxy | Low | Free, Apache-2.0 | | Docker Sandboxes | MicroVM with its own Docker daemon and workspace sync | Separate guest kernel | Not stated | Per Anthropic: any host with it installed | VM overhead | Network policies in its Security guide | Low | Free standalone product per Anthropic; admin policy is a paid tier | Docker hardening that gets you most of the way This is the baseline. Every flag below is documented in Docker's docker run reference[[6]](#cite-6). Run the container as a non-root user, because Claude Code requires that for the skip flag anyway. docker run --rm -it \ --user 1000:1000 \ --read-only \ --tmpfs /tmp:rw,noexec,nosuid,size=512m \ --tmpfs /home/agent/.cache:rw,nosuid,size=1g \ --cap-drop ALL \ --security-opt no-new-privileges \ --pids-limit 512 \ --memory 4g \ --network agent_net \ -e HTTPS_PROXY=http://proxy:3128 \ -e HTTP_PROXY=http://proxy:3128 \ -v "$PWD":/work \ -w /work \ my-agent-image claude What each line buys you: --read-only stops the agent persisting malware or editing system files. --cap-drop ALL removes every Linux capability; Docker's default is already an allowlist, and dropping all is stricter[[5]](#cite-5). no-new-privileges blocks setuid escalation. The default seccomp profile stays on unless you disable it, and you can swap in your own with --security-opt seccomp=/path/profile.json[[7]](#cite-7). Mount only the project directory. Never mount ~/.ssh, cloud credential files or the Docker socket. Pass a repo-scoped, short-lived token as an environment variable instead. The remaining gap is the network. Put the agent on an internal network with no route out, and attach a proxy to both that network and a normal one: services: agent: image: my-agent-image user: "1000:1000" read_only: true cap_drop: [ALL] security_opt: ["no-new-privileges:true"] pids_limit: 512 mem_limit: 4g tmpfs: ["/tmp:rw,noexec,nosuid,size=512m"] environment: HTTPS_PROXY: http://proxy:3128 HTTP_PROXY: http://proxy:3128 volumes: ["./:/work"] working_dir: /work networks: [agent_net] proxy: image: ubuntu/squid volumes: - ./squid.conf:/etc/squid/squid.conf:ro - ./allowed-domains.txt:/etc/squid/allowed-domains.txt:ro networks: [agent_net, egress] networks: agent_net: internal: true egress: {} In squid.conf, the allowlist is three lines: acl allowed dstdomain "/etc/squid/allowed-domains.txt", http_access allow allowed, http_access deny all. Start the domain file with api.anthropic.com or api.openai.com, plus your package registry, and add hosts only when a build fails and you agree it should succeed. Anthropic's dev container uses the same default-deny idea through an iptables script, and says the skip flag should be paired with egress restrictions[[2]](#cite-2). If you would rather not assemble and test this yourself, the [WOWHOW Agent Sandbox Kit](/product/agent-sandbox-kit) ($29) ships the hardened Docker config, a Squid default-deny allowlist and a smoke test that proves the egress rules hold. The catch: proxy variables only constrain tools that honor them. curl, npm and git over HTTPS do. Raw TCP clients do not, but on an internal: true network they have no route anyway, which is why the internal network does the real enforcement and the proxy only supplies the exception list. When gVisor (runsc) is worth it gVisor is an application kernel. Its Sentry implements the Linux interface in Go and, per the docs, does not pass system calls through to the host kernel. A Gofer process mediates file access[[8]](#cite-8). The host kernel sees a handful of calls from the Sentry instead of everything the agent's processes issue, so a kernel bug reachable from a syscall is harder to hit. It runs as an OCI runtime, so Docker treats it as a drop-in. Register it: sudo /usr/local/bin/runsc install sudo systemctl reload docker docker run --rm --runtime=runsc hello-world runsc install edits Docker's runtime configuration for you[[9]](#cite-9). Install the binary first using gVisor's tarball or apt package. After that, add --runtime=runsc to the hardened docker run above. For no network at all, runsc accepts --network=none, which leaves only a loopback[[11]](#cite-11). The price is compatibility and speed. gVisor's compatibility table for amd64 covers 352 syscalls: 290 implemented fully or partly, 62 not at all. Unimplemented examples include userfaultfd, perf_event_open (returns no such device), io_uring_register and vmsplice. io_uring and ptrace are only partly supported[[10]](#cite-10). For an agent that runs npm, pytest and git, this rarely bites. It bites profilers, debuggers using perf, and anything built on io_uring. On performance, gVisor's own page says CPU-bound work runs natively while syscall-heavy and small-file, VFS-heavy workloads pay the most, and it recommends the Systrap platform for best performance[[12]](#cite-12). A big node_modules install is exactly the file-heavy case, so time it before you commit. When a microVM is justified A microVM gives the workload its own kernel. A guest kernel exploit lands inside the VM, and the attacker still needs a hypervisor escape. Anthropic's sandbox page makes the same call: a dedicated VM is the strongest separation and fits untrusted code or policy that demands kernel-level separation[[4]](#cite-4). Justify it when: - Several customers or teams share one host (multi-tenant agents). - You run CI runners that execute pull-request code from strangers. - You build a Codex-cloud-style service where each task gets a fresh machine. Firecracker needs read/write access to /dev/kvm on x86_64 or aarch64 Linux and advertises boot under 125 ms and under 5 MiB overhead per VM[[13]](#cite-13). The one-liner, from its getting-started guide, boots from a JSON config holding the kernel and rootfs: sudo ./firecracker --api-sock /tmp/firecracker.socket --config-file vm-config.json Building the kernel image, rootfs and tap networking is a project of its own[[14]](#cite-14). Kata Containers wraps a lightweight VM behind a containerd shimv2 runtime so Kubernetes can schedule it like a pod, and kata-runtime check tests whether a host can run it[[15]](#cite-15). Follow the Kata install guide for the runtime-class registration rather than copying a snippet from memory. For a single developer who wants VM isolation without the assembly, Docker Sandboxes (a microVM with its own Docker daemon) is the lower-effort route Anthropic points to[[4]](#cite-4). Apple container on macOS 26 Apple's open-source container tool runs Linux containers as lightweight virtual machines on a Mac. It needs Apple silicon, supports macOS 26 only, is Apache-2.0, and builds on the Containerization Swift package. Install the signed package from the GitHub releases page, then: container system start container run --rm alpine echo hello The README says the project is under active development, release versions are product versions rather than semantic versions, and experimental features may change[[16]](#cite-16). Which one to pick Solo developer, trusted repo, Linux or Mac: hardened Docker plus the egress proxy, then the vendor's built-in sandbox inside it. Running agents you cannot supervise on code you did not write: add --runtime=runsc if your toolchain passes a smoke run, or move to a microVM. Selling agent runs to other people: microVM, no debate. Whichever you choose, cap the money side too, since a contained agent can still burn tokens. See [Claude Code spend limits and Codex runaway bills](/blogs/claude-code-spend-limit-hard-caps-codex-runaway-bill-2026), price a run with the [agent run cost simulator](/tools/agent-run-cost-simulator), and check that the Codex daemon is not leaving state behind in [this disk usage guide](/blogs/codex-cli-daemon-background-process-disk-usage-how-to-turn-off-2026). Quick answers Is --dangerously-skip-permissions safe inside Docker? Safer, not safe. The container limits file and process damage, but Anthropic warns a malicious project can still exfiltrate anything reachable inside it, including Claude credentials. Add egress restrictions, avoid mounting host secrets, and use a non-root user, which the flag requires. Does Docker isolate the kernel? No. Containers share the host kernel and rely on namespaces, cgroups, capabilities and seccomp. That is enough against a misbehaving agent and not enough against a determined attacker with a kernel exploit, which is the gap gVisor and microVMs close. Is gVisor or a microVM stronger? A microVM, in general, because the boundary is a hypervisor and a separate guest kernel. gVisor shrinks the host kernel surface but still runs on the host kernel. gVisor is easier to adopt because it plugs into Docker as --runtime=runsc. What does Codex do by default for network access? It is off. The default preset runs workspace-write with network disabled, and you enable it with network_access = true under [sandbox_workspace_write]. Using --yolo removes the sandbox entirely, so put it inside a container. Can I use Apple container to sandbox agents on a Mac? Yes, on Apple silicon with macOS 26. It runs each Linux container as a lightweight VM. It is under active development, so pin the version and test before relying on it for anything unattended. Sources 1. Claude Code: configure the sandboxed Bash tool (accessed 16 October 2026) 2. Claude Code: development containers (accessed 16 October 2026) 3. OpenAI Codex: agent approvals and security (formerly developers.openai.com/codex, accessed 16 October 2026) 4. Claude Code: choose a sandbox environment (accessed 16 October 2026) 5. Docker Engine security (accessed 16 October 2026) 6. docker container run reference (accessed 16 October 2026) 7. Docker seccomp security profiles (accessed 16 October 2026) 8. gVisor documentation (accessed 16 October 2026) 9. gVisor installation (accessed 16 October 2026) 10. gVisor Linux amd64 syscall compatibility (accessed 16 October 2026) 11. gVisor networking (accessed 16 October 2026) 12. gVisor performance guide (accessed 16 October 2026) 13. Firecracker project site (accessed 16 October 2026) 14. Firecracker getting started (accessed 16 October 2026) 15. Kata Containers repository (accessed 16 October 2026) 16. Apple container repository (accessed 16 October 2026) Every product mentioned is available at wowhow.cloud — pay once, ship forever. --- Originally published at wowhow.cloud
You missed the point by focusing on the wrong part (containers) instead of the part that's relevant (kill darwin CLI userland). Imagine the only scriptability you get for the OS is Automator or Shortcuts, apple/container is at best an API at worst a GUI app and certainly not a CLI, and that's it. macOS is MacOS (pre-X). Or iOS-like. Terminal.app spawns a sandboxed Linux microvm. You never see the host from a shell. Dear colima can't even _exist_.