How to Sandbox Hermes with Docker Desktop?

The familiar route — run Hermes inside a Docker container on macOS Sonoma, with one bind-mounted folder as the only link to the host.

Setup time ~30 minutes
Disk budget ~15 GB (cap at 20 GB)
One-time cost Free
Going cost Free for personal & small teams; paid over 250 employees / $10M revenue

Ingredients

This is the choice when your team already runs Docker Desktop, when your CI builds the same container image, or when you simply prefer a stack that everyone has heard of. The trade-offs against OrbStack are slower file sharing, more idle RAM, and a licence to mind at larger organisations.

1 Install Docker Desktop

brew install --cask docker

Launch Docker Desktop once so it can install its helper and accept the licence terms. Verify the engine is up:

docker version
docker run --rm hello-world

2 Cap the VM resources

Open Docker Desktop → Settings → Resources → Advanced and set:

Click Apply & restart. Docker Desktop will recreate the virtual disk to the new size.

Important: on the same Resources screen, turn on the VirtioFS file-sharing implementation if it is not already on. The older gRPC FUSE backend is several times slower for the read/write traffic an agent produces.

3 Lock down the file-sharing list

By default Docker Desktop allows containers to bind-mount almost anywhere under /Users. We want exactly one folder.

mkdir -p ~/hermes-workspace

In Settings → Resources → File sharing, remove the broad /Users entry and add only:

Apply and restart. From now on any container that tries to mount a path outside that folder fails at start.

4 Write the Dockerfile

Pin the Python, install fnm, install Node, install Hermes. Keep this in ~/hermes-image/Dockerfile on the Mac:

FROM python:3.12-slim-bookworm

ENV DEBIAN_FRONTEND=noninteractive \
    HERMES_WORKSPACE=/workspace \
    PATH=/root/.local/share/fnm:/root/.local/bin:$PATH

RUN apt-get update && apt-get install -y --no-install-recommends \
        curl ca-certificates git build-essential unzip && \
    rm -rf /var/lib/apt/lists/*

# Node via fnm, isolated to this image
RUN curl -fsSL https://fnm.vercel.app/install | bash -s -- --skip-shell && \
    /root/.local/share/fnm/fnm install 22 && \
    /root/.local/share/fnm/fnm default 22

# Hermes itself
RUN git clone https://github.com/NousResearch/hermes-agent.git /opt/hermes && \
    pip install --no-cache-dir -e /opt/hermes

WORKDIR /workspace
CMD ["hermes", "run", "--workspace", "/workspace"]

Build the image:

cd ~/hermes-image
docker build -t hermes-sandbox:latest .

5 Run the container with one mount

docker run -it --rm \
    --name hermes \
    --memory=4g --cpus=4 \
    --read-only \
    --tmpfs /tmp:rw,size=512m \
    --tmpfs /root:rw,size=1g \
    -v ~/hermes-workspace:/workspace \
    hermes-sandbox:latest

What each flag does:

6 Verify the seam

On the host:

echo "hello from the mac" > ~/hermes-workspace/in.txt

Inside the container (in the running Hermes prompt or a second shell with docker exec -it hermes bash):

cat /workspace/in.txt
echo "hello from the sandbox" > /workspace/out.txt

Back on the host:

cat ~/hermes-workspace/out.txt

That is the entire surface area of the sandbox.

Making it stick across reboots

--rm throws the container away when it exits, which is usually what you want for safety. If you need state to survive restarts — for example Hermes’ own model cache — add a named volume inside the container instead of mounting another host folder:

docker volume create hermes-state

docker run -it --rm \
    --name hermes \
    -v hermes-state:/var/lib/hermes \
    -v ~/hermes-workspace:/workspace \
    hermes-sandbox:latest

Named volumes live inside the Docker VM, never on your Mac filesystem.

What you end up with

A reproducible Hermes image that any teammate can rebuild from the same Dockerfile, capped at 20 GB of virtual disk, with one bind-mount as its only path to your Mac. Throw away the container any time — the workspace folder survives, everything else dies.

Back to the main recipe

← How to Run Hermes in a macOS Sandbox?

Further reading