docker-claude/CLAUDE.md
docker-claude e0e5e03e58 feat(docker): add isolated Claude Code environment with proxy sidecar
Two-container setup: claude (UID 1000, internal-only network) and proxy
(Squid, UID 13). The internal Docker network uses internal: true so the
claude container has no direct internet route. All egress is tunnelled
through the Squid sidecar which enforces a domain allowlist. Both
containers drop all capabilities and set no-new-privileges. claude.sh
provides start/stop/run/update/logs/status/shell lifecycle management.
2026-04-14 17:23:02 +02:00

3.6 KiB

Project Guidance

This file provides context and guidance for working with this project.

Project Overview

docker-claude runs Claude Code inside a hardened Docker environment with a Squid proxy sidecar. The goal is full host encapsulation: Claude cannot access the host filesystem or network. All egress is routed through an allowlist-enforcing proxy.

Architecture

Two containers managed by Docker Compose:

  • claude — Claude Code CLI, non-root (UID 1000), isolated to an internal-only Docker network
  • proxy — Squid forward proxy, non-root (UID 13), bridges the internal network to the internet with an egress allowlist

Key Docker network property: claude-internal has internal: true, meaning Docker adds no default gateway. The claude container physically cannot reach the internet without going through the proxy container.

File Structure

docker-claude/
├── claude.sh             # Control script: start / stop / run / update / logs / status / shell
├── docker-compose.yml    # Service definitions and network topology
├── Dockerfile.claude     # Claude Code container (node:20-slim, UID 1000)
├── Dockerfile.proxy      # Squid proxy sidecar (ubuntu:22.04, UID 13)
├── proxy/
│   └── squid.conf        # Squid ACL config — egress allowlist lives here
├── .env.example          # Template for ANTHROPIC_API_KEY
├── .gitignore            # Excludes .env and logs
├── .dockerignore         # Keeps .env out of build context
└── README.md             # User documentation

Development Workflow

chmod +x claude.sh
cp .env.example .env      # set ANTHROPIC_API_KEY
./claude.sh start         # build + start proxy + launch Claude interactively
./claude.sh update        # rebuild images (no cache) after upstream updates

Coding Standards

  • Shell scripts use set -euo pipefail
  • Dockerfiles use --no-install-recommends and clean apt caches in the same layer
  • No capabilities granted; no-new-privileges on all containers
  • .env is never committed (enforced by .gitignore and .dockerignore)
  • Commit messages follow Angular format: type(scope): summary

Extending the Egress Allowlist

Add domains to proxy/squid.conf under the allowed_sites ACL, then rebuild:

docker compose -p claude-secure build proxy
./claude.sh stop && ./claude.sh start

Environment Persistence

This sandbox has a persistent environment file at /etc/sandbox-persistent.sh.

This file is automatically sourced in all shell contexts:

  • Non-interactive shells: via BASH_ENV=/etc/sandbox-persistent.sh
  • Login shells: via /etc/profile.d/sandbox-persistent.sh
  • Interactive shells: via /etc/bash.bashrc and ~/.bashrc

Critical: Shell Completions Must NOT Be in the Persistent Environment File

NEVER add shell completion scripts to /etc/sandbox-persistent.sh.

Shell completion scripts will completely break the bash tool when sourced via the persistent environment file.

Network access

There is a firewall in place to restrict outbound network access. If you need http/https access to an external service, request it by running:

sbx policy allow network [domain]

Git Authentication

The sandbox proxy handles GitHub authentication automatically by injecting credentials for HTTPS Git operations.

Additional Notes

  • Always read relevant files before making changes
  • Run tests after making modifications
  • Follow the existing code structure and patterns
  • You have sudo permissions, so you can install necessary packages
  • npm, pip and uv are already available for package management