4.5 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 (node:20-alpine), runs as the built-innodeuser (UID 1000), isolated to an internal-only Docker networkproxy— Squid forward proxy (alpine:3.21),squiduser, 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 and webui containers physically cannot reach the internet without going through the proxy container.
Auth supports three modes (checked at startup by claude.sh):
ANTHROPIC_API_KEY— API keyCLAUDE_CODE_OAUTH_TOKEN— 1-year token fromclaude setup-token(headless-friendly)- Neither set — Claude Code prompts for browser login on first run; port 54545 is published for the OAuth callback. Credentials persist in the
claude-confignamed volume.
File Structure
docker-claude/
├── claude.sh # Control script: start/stop/run/update/logs/status/shell
├── docker-compose.yml # Service definitions and network topology
├── claude/
│ └── Dockerfile # Claude Code (node:20-alpine, UID 1000)
├── proxy/
│ ├── Dockerfile # Squid proxy sidecar (alpine:3.21, squid user)
│ └── squid.conf # Squid ACL config — egress allowlist lives here
├── .env.example # Template for ANTHROPIC_API_KEY, WEBUI_PASSWORD, etc.
├── .gitignore # Excludes .env and logs
├── .dockerignore # Keeps .env out of build context
└── README.md # User documentation
Development Workflow
chmod +x claude.sh build.sh
cp .env.example .env # set ANTHROPIC_API_KEY
cd /path/to/project && ./claude.sh start # start proxy + launch Claude (pulls images, mounts CWD)
./claude.sh update # pull latest images from registry
./build.sh # build images locally (development)
Git Hooks
A pre-commit hook lives in hooks/ and enforces the executable bit on claude.sh and build.sh. Activate it once after cloning:
git config core.hooksPath hooks
Coding Standards
- Shell scripts use
set -euo pipefail - Dockerfiles use Alpine (
node:20-alpine,alpine:3.21) for minimal attack surface - Alpine packages use
apk add --no-cache; no apt cache cleanup layer needed - No capabilities granted;
no-new-privilegeson all containers .envis never committed (enforced by.gitignoreand.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.bashrcand~/.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