Skip to content

yury-egorenkov/claude-code-docker

Repository files navigation

Claude Code Docker

Run Claude Code in a sandboxed Docker container with network restrictions, persistent config, and batteries-included dev tooling.

Built with this setup and running in production: growity.ai and egorsky.com.

Why

Running an AI coding agent with full shell access on your host machine is a trust exercise. This project puts Claude Code inside a locked-down container where:

  • Claude state survives restarts — credentials, project memory, conversation history, and settings are mounted from the host (./node/), so you can rebuild or restart the container without losing context.
  • Network egress is restricted — only GitHub, npm, Anthropic APIs, and a handful of other services are reachable. Everything else is blocked by iptables.
  • Your host filesystem is isolated — only the workspace directory you choose gets mounted.
  • The environment is reproducible — same tools, same versions, every time.

Prerequisites

  • Docker
  • Make
  • An Anthropic API key (set via .env.properties or environment)

Quick Start

# Build the image and run interactively
make docker

# Or run in the background
make docker.run.d

On startup the container launches Claude Code directly. A cl alias is also available in the shell for subsequent runs.

What's in the Box

Category Tools
Runtime Node.js 20, Go 1.24.4
AI Claude Code CLI (@anthropic-ai/claude-code)
Shell Zsh with Oh My Zsh + Powerlevel10k, Bash
Git Git, delta (better diffs), GitHub CLI (gh)
Editors nano, vim
DB PostgreSQL client (psql)
Utilities jq, fzf, make, unzip, gow (Go watcher)
Network iptables, ipset, dig, ping

Configuration

Environment variables are loaded in order by the Makefile:

.env.default.properties    # checked in — sensible defaults
.env.properties            # git-ignored — your local overrides

You can point to a different config folder:

CONF=./conf/prod make docker.run

Key Variables

Variable Default Description
WORKSPACE /workspace Container workspace path
WORKSPACE_DIR (empty) Host subdirectory to mount as the workspace
DOCKER_LABEL claude Docker image label for tagging
ANTHROPIC_API_KEY Your Anthropic API key
ANTHROPIC_BASE_URL Custom API endpoint (e.g. for proxies)

Set secrets in .env.properties (never commit this file):

ANTHROPIC_API_KEY=sk-ant-...

Network Firewall

The container runs an iptables-based firewall (init-firewall.sh) that drops all outbound traffic by default and only allows connections to:

  • GitHub — API, web, and git protocol (IPs fetched dynamically from GitHub's /meta endpoint)
  • npmregistry.npmjs.org
  • Anthropicapi.anthropic.com, statsig.anthropic.com
  • VS Code — marketplace and update servers
  • Other — Sentry, Statsig, DNS (UDP 53), SSH (TCP 22), localhost, host network

The firewall self-verifies on startup: it confirms that example.com is unreachable and api.github.com is reachable. The container requires NET_ADMIN and NET_RAW capabilities.

VS Code Dev Container

Open this repo in VS Code and select Reopen in Container to get a fully configured dev environment with:

  • Claude Code, ESLint, Prettier, and GitLens extensions
  • Format-on-save with Prettier
  • Zsh as default terminal
  • Persistent bash history and Claude config across rebuilds
  • Firewall initialized automatically on start

See devcontainer.json for details.

Multi-Project Workflow

Mount different project directories using the shortcut targets:

make back      # mounts ../back
make front     # mounts ../front
make docs      # mounts ../docs
make markups   # mounts ../markups

Or mount any directory:

WORKSPACE_DIR=../my-project make docker.run

All Commands

make docker          # build + clean + run (default)
make docker.build    # build the image (tagged with git SHA)
make docker.run      # interactive run
make docker.run.d    # detached run
make docker.clean    # remove untagged project images
make docker.ls       # list project images
make help            # show all available commands

Local Shortcuts

For personal shortcuts that shouldn't be committed, create a local.makefile:

# DO NOT EVER INCLUDE IN GIT
# local.makefile — personal shortcuts, not tracked by the project makefile.
#
# Since Make only reads `makefile` (or `Makefile`) by default, you need to
# tell it about this file explicitly. The easiest way is a tiny shell helper:
#
#   mk() { make --makefile=local.makefile "$@"; }
#
# Drop that line in your ~/.bashrc or ~/.zshrc, then use it like:
#
#   mk back        # mount ../back and start Claude Code
#   mk front       # mount ../front
#   mk docs        # mount ../docs
#
# You can also invoke it directly without the helper:
#
#   make -f local.makefile back

back:
  $(MAKE) docker.run WORKSPACE_DIR=back

front:
  $(MAKE) docker.run WORKSPACE_DIR=front

ceo:
  $(MAKE) docker.run

License

MIT

About

Quickly run Claude code in a container—minimal setup required.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors