From 2d822305d13be7ac3a7c7d6abf100467ee4a5db4 Mon Sep 17 00:00:00 2001 From: docker-claude Date: Wed, 15 Apr 2026 17:02:43 +0200 Subject: [PATCH] refactor(images): pull from registry instead of building; add build.sh for local dev --- .env.example | 5 +++++ CLAUDE.md | 9 +++++---- README.md | 16 +++++++++++++--- build.sh | 17 +++++++++++++++++ claude.sh | 16 +++++----------- docker-compose.yml | 3 +++ 6 files changed, 48 insertions(+), 18 deletions(-) create mode 100755 build.sh diff --git a/.env.example b/.env.example index e8c6eea..9b353cd 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,11 @@ # Copy this file to .env and fill in your values. # .env is git-ignored — never commit it. +# ─── Image version ──────────────────────────────────────────────────────────── + +# Pin to a specific image tag. Defaults to "latest" if unset. +# IMAGE_TAG=0.1.42 + # ─── Authentication (choose one) ────────────────────────────────────────────── # Option 1: Anthropic API key diff --git a/CLAUDE.md b/CLAUDE.md index b9d8ea5..e65c01c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -44,11 +44,12 @@ docker-claude/ ## Development Workflow ```bash -chmod +x claude.sh +chmod +x claude.sh build.sh cp .env.example .env # set ANTHROPIC_API_KEY (and WEBUI_PASSWORD for web mode) -cd /path/to/project && ./claude.sh start # build + start proxy + launch Claude (mounts CWD as /workspace) -./claude.sh web # build + start proxy + webui (browser terminal on :7681) -./claude.sh update # rebuild images (no cache) after upstream updates +cd /path/to/project && ./claude.sh start # start proxy + launch Claude (pulls images, mounts CWD) +./claude.sh web # start proxy + webui (browser terminal on :7681) +./claude.sh update # pull latest images from registry +./build.sh # build images locally (development) ``` ## Coding Standards diff --git a/README.md b/README.md index 6f37c42..bdcab50 100644 --- a/README.md +++ b/README.md @@ -92,11 +92,12 @@ Then run `./claude.sh run` and follow the prompt. Credentials are stored in the ### CLI mode ```bash -# Build images, start proxy, launch Claude Code in the current directory +# Start proxy, launch Claude Code in the current directory +# (pulls images from registry.zeidler.dev on first run) cd ~/myproject ./claude.sh start -# Start proxy if needed, launch Claude Code (faster on subsequent runs) +# Start proxy if needed, launch Claude Code ./claude.sh run ``` @@ -123,13 +124,22 @@ sbx ports --publish 7681:7681/tcp ```bash ./claude.sh stop # Stop and remove all containers -./claude.sh update # Rebuild images without cache +./claude.sh update # Pull latest images from the registry ./claude.sh logs # Tail proxy logs ./claude.sh logs webui # Tail web interface logs ./claude.sh status # Show container status ./claude.sh shell # Debug bash shell in the Claude container ``` +### Building locally + +`build.sh` builds both images from source using the local Dockerfiles: + +```bash +./build.sh # build with layer cache +./build.sh --no-cache # force full rebuild +``` + ### Workspace | Mode | Workspace | diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..b761fdf --- /dev/null +++ b/build.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# build.sh — Build Docker images locally for development +# Usage: ./build.sh [--no-cache] [--push] +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" +PROJECT="claude-secure" + +GREEN='\033[0;32m'; NC='\033[0m' +info() { echo -e "${GREEN}[+]${NC} $*"; } + +dc() { docker compose -f "$COMPOSE_FILE" -p "$PROJECT" "$@"; } + +info "Building images..." +dc build "$@" +info "Done. Run './claude.sh start' to launch." diff --git a/claude.sh b/claude.sh index c9d3ff8..9067b97 100644 --- a/claude.sh +++ b/claude.sh @@ -122,12 +122,8 @@ dc() { docker compose -f "$COMPOSE_FILE" -p "$PROJECT" "$@"; } cmd_start() { check_deps load_env - info "Building images..." - dc build info "Starting proxy sidecar..." dc up -d proxy - info "Waiting for proxy health check..." - dc up -d proxy # no-op if already healthy; compose waits via depends_on info "Launching Claude Code..." # shellcheck disable=SC2046 dc run --rm --service-ports $(workspace_flag) $(kube_flag) claude "$@" @@ -152,8 +148,8 @@ cmd_run() { cmd_update() { check_deps - info "Rebuilding images (no cache)..." - dc build --no-cache + info "Pulling latest images from registry..." + dc pull info "Update complete. Run './claude.sh start' to launch." } @@ -183,8 +179,6 @@ cmd_web() { error "WEBUI_PASSWORD is not set. Add it to .env before starting the web interface." exit 1 fi - info "Building images..." - dc build info "Starting proxy and web interface..." dc up -d webui local port=7681 @@ -206,12 +200,12 @@ cmd_help() { Usage: $(basename "$0") [args] Commands: - start [args] Build images, start proxy, launch Claude Code (CLI) + start [args] Start proxy, launch Claude Code (CLI) run [args] Start proxy if needed, launch Claude Code (CLI) - web Build images, start proxy + web interface (browser terminal) + web Start proxy + web interface (browser terminal) web-stop Stop the web interface (keeps proxy running) stop Stop and remove all containers - update Rebuild images without cache + update Pull latest images from the registry logs [svc] Tail logs (default: proxy) status Show container status shell Open a bash shell in the Claude container (debug) diff --git a/docker-compose.yml b/docker-compose.yml index e215390..c7d9b26 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: # Bridges the isolated internal network to the internet. # Enforces an egress allowlist — see proxy/squid.conf. proxy: + image: registry.zeidler.dev/docker/playground/docker-claude-proxy:${IMAGE_TAG:-latest} build: context: proxy dockerfile: Dockerfile @@ -24,6 +25,7 @@ services: # No direct internet access. All egress routes through the proxy sidecar. # Run via "docker compose run --rm --service-ports claude" (managed by claude.sh). claude: + image: registry.zeidler.dev/docker/playground/docker-claude-claude:${IMAGE_TAG:-latest} build: context: claude/ dockerfile: Dockerfile @@ -64,6 +66,7 @@ services: # Protected by HTTP basic auth — set WEBUI_USER / WEBUI_PASSWORD in .env. # Network isolation is identical to the CLI container. webui: + image: registry.zeidler.dev/docker/playground/docker-claude-claude:${IMAGE_TAG:-latest} build: context: claude/ dockerfile: Dockerfile