- setup.sh: interactive wizard for Docker check and auth configuration - launch.sh: folder-picker launcher (macOS native dialog, zenity/kdialog on Linux, text fallback) - launch.bat: Windows launcher using PowerShell folder browser + Git Bash - claude.sh: friendlier error messages with actionable links; prompt setup.sh if .env missing - hooks/pre-commit: add setup.sh and launch.sh to executable enforcement - README: add Quick Start section aimed at non-technical users Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
152 lines
5.6 KiB
Markdown
152 lines
5.6 KiB
Markdown
# docker-claude
|
|
|
|
Runs [Claude Code](https://claude.ai/code) inside an isolated Docker environment with a proxy sidecar for controlled egress. Claude cannot access the host filesystem or network directly.
|
|
|
|
## Quick Start
|
|
|
|
**1. Install Docker Desktop**
|
|
|
|
Download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/) for your platform. It's free and includes everything needed — no extra tools required.
|
|
|
|
**2. Download this repo**
|
|
|
|
Clone or download and unzip this repository somewhere on your machine.
|
|
|
|
**3. Run setup**
|
|
|
|
- **macOS / Linux:** Open a terminal, navigate to the folder, and run:
|
|
```bash
|
|
./setup.sh
|
|
```
|
|
- **Windows:** Double-click `launch.bat` — it will run setup automatically on first launch.
|
|
|
|
Setup will ask how you want to authenticate (API key, subscription token, or browser login) and save your settings.
|
|
|
|
**4. Start Claude**
|
|
|
|
- **macOS / Linux:** Double-click `launch.sh`, or run it from a terminal:
|
|
```bash
|
|
./launch.sh
|
|
```
|
|
A folder picker will appear — select the project you want Claude to work on.
|
|
|
|
- **Windows:** Double-click `launch.bat`.
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────┐
|
|
│ Host machine │
|
|
│ │
|
|
│ claude.sh (control script) │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
|
│ │ Docker: claude-secure │ │
|
|
│ │ │ │
|
|
│ │ ┌─────────────┐ claude-internal │ │
|
|
│ │ │ claude │ (internal: true) │ │
|
|
│ │ │ (UID 1000) │──────────────► ┌──────────┐ │ │
|
|
│ │ └─────────────┘ │ proxy │ │ │
|
|
│ │ │ (UID 13) │ │ │
|
|
│ │ └────┬─────┘ │ │
|
|
│ │ proxy-external │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ internet (allowlisted) │
|
|
└──────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
- **`claude`** — Claude Code CLI (`node:20-alpine`), runs as the built-in `node` user (UID 1000), on `claude-internal` only
|
|
- **`proxy`** — Squid forward proxy (`alpine:3.21`), bridges `claude-internal` ↔ internet with egress allowlist
|
|
- **`claude-internal`** — `internal: true`; no default gateway, containers cannot reach the internet directly
|
|
- **`proxy-external`** — Standard bridge; proxy sidecar only
|
|
|
|
## Prerequisites
|
|
|
|
- [Docker Desktop](https://www.docker.com/products/docker-desktop/) (includes Docker Engine and Compose)
|
|
|
|
## Authentication
|
|
|
|
Three options — `./setup.sh` will guide you through picking one:
|
|
|
|
### Option 1 — API key
|
|
```bash
|
|
ANTHROPIC_API_KEY=sk-ant-...
|
|
```
|
|
Get a key at [console.anthropic.com](https://console.anthropic.com/settings/keys).
|
|
|
|
### Option 2 — OAuth token (subscription, headless-friendly)
|
|
|
|
Run this **on your host** (not inside the container) to generate a 1-year token:
|
|
```bash
|
|
claude setup-token
|
|
```
|
|
Then paste the token into setup, or set it manually in `.env`:
|
|
```bash
|
|
CLAUDE_CODE_OAUTH_TOKEN=...
|
|
```
|
|
|
|
### Option 3 — Browser OAuth (interactive)
|
|
|
|
Leave both keys unset. On first run, Claude Code will print a login URL.
|
|
Port 54545 must be reachable from your browser for the OAuth callback.
|
|
|
|
## Usage
|
|
|
|
### Normal use
|
|
|
|
```bash
|
|
./launch.sh # folder picker → starts Claude in the selected directory
|
|
```
|
|
|
|
### CLI / power users
|
|
|
|
```bash
|
|
cd ~/myproject
|
|
./claude.sh start
|
|
|
|
./claude.sh stop # Stop and remove all containers
|
|
./claude.sh update # Pull latest images from the registry
|
|
./claude.sh logs # Tail proxy logs
|
|
./claude.sh status # Show container status
|
|
./claude.sh shell # Debug bash shell in the Claude container
|
|
```
|
|
|
|
### Building locally
|
|
|
|
```bash
|
|
./build.sh # build with layer cache
|
|
./build.sh --no-cache # force full rebuild
|
|
```
|
|
|
|
## Egress allowlist
|
|
|
|
Edit `proxy/squid.conf` and add domains to the `allowed_sites` ACL:
|
|
|
|
```
|
|
acl allowed_sites dstdomain api.anthropic.com
|
|
acl allowed_sites dstdomain statsig.anthropic.com
|
|
# acl allowed_sites dstdomain api.github.com
|
|
# acl allowed_sites dstdomain registry.npmjs.org
|
|
```
|
|
|
|
Rebuild after changes:
|
|
|
|
```bash
|
|
./claude.sh stop && ./claude.sh start
|
|
```
|
|
|
|
## Security controls
|
|
|
|
| Control | claude | proxy |
|
|
|---|---|---|
|
|
| Non-root user | UID 1000 (`node`, built into base image) | `squid` user |
|
|
| `no-new-privileges` | yes | yes |
|
|
| All capabilities dropped | yes | yes |
|
|
| Direct internet access | no (`internal` network only) | allowlisted only |
|
|
| Host filesystem | CWD mounted as `/workspace` | none |
|
|
| Docker socket | not mounted | not mounted |
|