v1 - basic functionality
This commit is contained in:
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
FROM node:22-slim
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
git \
|
||||||
|
ripgrep \
|
||||||
|
bash \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create a non-root user with a real home directory
|
||||||
|
RUN useradd -m -s /bin/bash -u 1001 coder
|
||||||
|
|
||||||
|
# Ensure ~/.local/bin is on PATH (where the native installer puts the binary)
|
||||||
|
ENV PATH="/home/coder/.local/bin:/home/coder/.claude/bin:${PATH}"
|
||||||
|
|
||||||
|
# Copy entrypoint (as root, then lock down)
|
||||||
|
COPY --chmod=755 entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
|
||||||
|
USER coder
|
||||||
|
WORKDIR /code
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
|
CMD ["bash"]
|
||||||
76
README.md
Normal file
76
README.md
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# Claude Code — Dockerized
|
||||||
|
|
||||||
|
A minimal, guardrailed container for running Claude Code. The home
|
||||||
|
directory and project folder are volumes, keeping your Claude install
|
||||||
|
and credentials separate from any specific project.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Build the image
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
# 2. Export your API key (or put it in a .env file)
|
||||||
|
export ANTHROPIC_API_KEY=sk-ant-...
|
||||||
|
|
||||||
|
# 3. First run — installs Claude Code into the home volume, then drops you
|
||||||
|
# into an interactive shell inside the default ./code directory
|
||||||
|
docker compose run --rm claude-code
|
||||||
|
```
|
||||||
|
|
||||||
|
On first start the entrypoint runs the native installer and places the
|
||||||
|
binary in the `claude-home` named volume (under `/home/coder/.local/bin`).
|
||||||
|
Subsequent starts skip the install and launch immediately.
|
||||||
|
|
||||||
|
## Switching projects
|
||||||
|
|
||||||
|
Point `PROJECT_DIR` at any directory on your host:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PROJECT_DIR=/path/to/myproject docker compose run --rm claude-code
|
||||||
|
```
|
||||||
|
|
||||||
|
Or set it in a `.env` file:
|
||||||
|
|
||||||
|
```
|
||||||
|
ANTHROPIC_API_KEY=sk-ant-...
|
||||||
|
PROJECT_DIR=/Users/me/projects/my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
Then just:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose run --rm claude-code
|
||||||
|
```
|
||||||
|
|
||||||
|
## Starting Claude Code
|
||||||
|
|
||||||
|
Once inside the container shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude # start an interactive session in the current directory
|
||||||
|
claude --help # show available options
|
||||||
|
claude doctor # diagnose installation issues
|
||||||
|
```
|
||||||
|
|
||||||
|
## Volumes
|
||||||
|
|
||||||
|
| Volume | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `claude-home` (named) | Persists Claude Code binary, config, and auth credentials |
|
||||||
|
| `$PROJECT_DIR` (bind) | Your project code — swap freely between sessions |
|
||||||
|
|
||||||
|
To wipe the Claude install and start fresh:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down -v # removes the claude-home volume
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security notes
|
||||||
|
|
||||||
|
- Runs as a non-root user (`coder`, uid 1000)
|
||||||
|
- All Linux capabilities are dropped (`cap_drop: ALL`)
|
||||||
|
- Privilege escalation is disabled (`no-new-privileges`)
|
||||||
|
- The container has no network restrictions beyond what Docker provides —
|
||||||
|
add a custom network or `--network none` with `--add-host` if you want
|
||||||
|
to lock that down further
|
||||||
37
docker-compose.yml
Normal file
37
docker-compose.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
services:
|
||||||
|
claude-code:
|
||||||
|
build: .
|
||||||
|
image: claude-code:local
|
||||||
|
container_name: claude-code
|
||||||
|
|
||||||
|
# Pass your Anthropic API key in from the host environment,
|
||||||
|
# or drop it into a .env file alongside this compose file.
|
||||||
|
# environment:
|
||||||
|
# - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:?Set ANTHROPIC_API_KEY in your environment or .env file}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
# Fixed home volume — persists Claude Code install, config, and credentials
|
||||||
|
# across container restarts and image rebuilds.
|
||||||
|
- claude-home:/home/coder
|
||||||
|
|
||||||
|
# Swappable project folder — override PROJECT_DIR to point at any directory:
|
||||||
|
# PROJECT_DIR=/path/to/myproject docker compose run --rm claude-code
|
||||||
|
- ${PROJECT_DIR:-./code}:/code
|
||||||
|
|
||||||
|
# Drop all Linux capabilities and disable privilege escalation —
|
||||||
|
# Claude Code doesn't need any of them.
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
|
||||||
|
# Interactive terminal so `claude` works properly
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
working_dir: /code
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
claude-home:
|
||||||
|
# Named volume — Docker manages it; survives `docker compose down`
|
||||||
|
# (use `docker compose down -v` to wipe it along with the install)
|
||||||
15
entrypoint.sh
Normal file
15
entrypoint.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Install Claude Code if not already present in the home volume.
|
||||||
|
# Because the home directory is a volume, this install persists across
|
||||||
|
# container restarts and rebuilds.
|
||||||
|
if ! command -v claude &>/dev/null; then
|
||||||
|
echo "Claude Code not found — running installer..."
|
||||||
|
curl -fsSL https://claude.ai/install.sh | bash
|
||||||
|
echo "Claude Code installed successfully."
|
||||||
|
else
|
||||||
|
echo "Claude Code $(claude --version 2>/dev/null || echo '(version unknown)') ready."
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
13
safeclaude
Executable file
13
safeclaude
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ $# -lt 1 ]]; then
|
||||||
|
echo "Usage: $(basename "$0") <path-to-project>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROJECT_DIR="$(cd "$1" && pwd)" # resolve to absolute path
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
|
||||||
|
|
||||||
|
PROJECT_DIR="$PROJECT_DIR" docker compose -f "$SCRIPT_DIR/docker-compose.yml" run -w /code --rm claude-code claude
|
||||||
Reference in New Issue
Block a user