8f9005582b
On Linux the guest kernel's LOCAL routing table routes all 127.0.0.0/8 to the guest's own loopback interface (priority 0, checked before any main-table route), so TSI never sees connections to the per-bottle loopback alias — the fix_guest_ loopback_routing approach confirmed this at the kernel level. Use the per-bottle docker bridge gateway (192.168.N.1) instead. It is not a loopback address, so the guest routes it via eth0 and TSI intercepts it normally. The TSI allowlist remains a /32 that is distinct from the container IP (192.168.N.2), so direct bypass to egress:9099 is still blocked by TSI. Changes: - Add _proxy_host() helper: returns bundle_gateway on Linux, loopback alias on macOS - Thread proxy_host through _start_bundle, _discover_urls, _launch_vm, and _bundle_launch_spec (publish_host_ip) - Remove _fix_guest_loopback_routing (no longer needed) - Relax proxy-URL assertion in the integration test to accept any http://IP:port (with a comment explaining the difference) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
73 lines
3.1 KiB
Docker
73 lines
3.1 KiB
Docker
# bot-bottle container image.
|
|
#
|
|
# Goal: a small, cache-friendly base that ships claude-code (the
|
|
# `@anthropic-ai/claude-code` npm package, CLI name `claude`) ready to run
|
|
# interactively. The container is ephemeral; per PRD 0001 v1 the host
|
|
# filesystem is not mounted in.
|
|
#
|
|
# Layer ordering is deliberate: the npm install lives in its own layer so
|
|
# changes to the rest of the repo (or to the CMD) don't bust it.
|
|
|
|
# Current Node LTS; slim variant keeps the image small while still
|
|
# providing apt-get for any future additions.
|
|
FROM node:22-slim
|
|
|
|
# Install runtime system deps. claude-code shells out to git for several
|
|
# features (status checks, commits, PR creation) — without git in the
|
|
# image, those features fail in surprising ways once the user does any
|
|
# real work. ca-certificates is already in the slim base; listed for
|
|
# clarity in case the base ever drops it. curl is here so any
|
|
# HTTPS_PROXY-aware tool (curl itself, plus anything that shells out
|
|
# to it) works against egress's bumped TLS without the agent needing
|
|
# local DNS.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends git ca-certificates curl ripgrep iproute2 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# App-specific deps. Python isn't required by claude-code itself
|
|
# (claude-code is a Node CLI), but is convenient for the agent to
|
|
# shell out to for ad-hoc scripts. Kept on its own layer so it can
|
|
# be moved to a downstream image if the base ever needs to shrink.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends python3 python3-pip python3-venv \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install claude-code globally. Pinned to the version verified in the v1
|
|
# build (`claude --version` returns 2.1.126). Bump deliberately when
|
|
# rolling forward; an unpinned install would mean rebuilds silently pick
|
|
# up new behavior.
|
|
RUN npm install -g --no-fund --no-audit @anthropic-ai/claude-code@2.1.172 \
|
|
&& npm cache clean --force
|
|
|
|
# Run as a non-root user. The node image already provides a `node` user
|
|
# (uid 1000) with a home directory, which is where claude-code will write
|
|
# its session state.
|
|
USER node
|
|
WORKDIR /home/node
|
|
|
|
# Pre-create the skills directory so PRD 0002's host->container skill
|
|
# copier (bot_bottle/skills.py) drops files into a path owned by the
|
|
# `node` user. `skills_copy_into` also `mkdir -p`s defensively, but
|
|
# baking it into the image avoids a permission-confusion footgun if a
|
|
# future change to the launcher copies in as a different user.
|
|
RUN mkdir -p /home/node/.claude/skills
|
|
|
|
# Heredoc delimiter is unquoted so $HOME expands; no other `$` appears
|
|
# in the body, so this is safe under dash (Docker's default RUN shell).
|
|
RUN cat > "$HOME/.claude.json" <<JSON
|
|
{
|
|
"hasCompletedOnboarding": true,
|
|
"theme": "dark",
|
|
"bypassPermissionsModeAccepted": true,
|
|
"projects": {
|
|
"$HOME": { "hasTrustDialogAccepted": true }
|
|
}
|
|
}
|
|
JSON
|
|
|
|
# Default to an interactive claude session. In the v1 launcher,
|
|
# `bot_bottle/cli/start.py` runs the container detached and uses `docker exec`
|
|
# to attach a TTY, but this CMD makes `docker run -it bot-bottle-claude` also
|
|
# do something useful for ad-hoc debugging.
|
|
CMD ["claude"]
|