Files
bot-bottle/tests/unit
didericis-claude f4026ea3ae
test / unit (pull_request) Successful in 26s
test / integration (pull_request) Successful in 42s
fix(smolmachines): docker push fails on Docker Desktop — daemon-side route differs from host loopback
`./cli.py start <agent>` under CLAUDE_BOTTLE_BACKEND=smolmachines
died at `docker push localhost:<port>/claude-bottle:<id>` with
`Get "http://localhost:<port>/v2/": context deadline exceeded`.

Cause: chunk 4c bound the ephemeral registry to `127.0.0.1::5000`
and used `localhost:<port>` as the only image-ref hostname. On
Docker Desktop the daemon runs inside its own Linux VM — its
`localhost` is the VM's loopback, not the host's, so the daemon
cannot reach a registry bound to the host's 127.0.0.1.

Fix: bind the registry to all interfaces (`-p :5000`) so it's
reachable from both sides, and yield two endpoints:

  - `daemon_endpoint` — `host.docker.internal:<port>` on Docker
    Desktop (daemon-side hostname for the host VM gateway),
    `localhost:<port>` on a native Linux daemon that shares the
    host's network namespace. Used for `docker tag` + `docker
    push`.
  - `host_endpoint` — always `localhost:<port>`. Used for
    `smolvm pack create`, which runs as a host process.

The registry stores images by repo+tag, so a push to
`host.docker.internal:<port>/cb:<id>` and a pull from
`localhost:<port>/cb:<id>` resolve to the same blob — the
hostname in a ref is just routing.

Detection uses `docker info --format '{{.OperatingSystem}}'`,
which returns "Docker Desktop" on macOS/Windows Desktop and the
host's OS name on native daemons.

Trade-off: all-interface binding briefly publishes the registry
on every interface (~5-10s during prepare). The pushed image is
built from the public repo Dockerfile (no secrets), the port is
random, and the window is short — acceptable for v1 of a
personal dev tool.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 14:41:26 -04:00
..