services: # ─── Proxy sidecar ───────────────────────────────────────────────────────── # Bridges the isolated internal network to the internet. # Enforces an egress allowlist — see proxy/squid.conf. proxy: build: context: . dockerfile: Dockerfile.proxy networks: - claude-internal # reachable by the claude container - proxy-external # has outbound internet access restart: unless-stopped security_opt: - no-new-privileges:true cap_drop: - ALL read_only: true tmpfs: - /tmp - /var/spool/squid - /var/log/squid # ─── Claude Code container ───────────────────────────────────────────────── # No direct internet access. All egress routes through the proxy sidecar. # Run via "docker compose run --rm claude" (managed by claude.sh). claude: build: context: . dockerfile: Dockerfile.claude depends_on: proxy: condition: service_healthy networks: - claude-internal # only — no route to the internet environment: - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - HTTP_PROXY=http://proxy:3128 - HTTPS_PROXY=http://proxy:3128 - ALL_PROXY=http://proxy:3128 - NO_PROXY=localhost,127.0.0.1 security_opt: - no-new-privileges:true cap_drop: - ALL stdin_open: true tty: true # Workspace is injected by claude.sh via --volume flag at run time. # Default: named Docker volume. Override: set WORKSPACE_DIR on the host. networks: # Internal-only: Docker adds no default gateway → no direct internet route claude-internal: driver: bridge internal: true # External: standard bridge with internet access (proxy only) proxy-external: driver: bridge