Notes: The docker-compose.local.yaml and the Dockerfile need to reside in the same directory as the script (~/bin, etc). Otherwise you need to specify full paths in the script.
I've used Linuxbrew as my default image here to get a bunch of tools in their newest versions without any hassle. Also, you can easily instruct Claude to get whatever it needs by running brew install. The downsides are: the image can get quite large, Homebrew gets constant updates, so your images will rebuild often, sometimes at unexpected moments. I guess NixOS might be a reasonable alternative here. TBD.
Usage:
- Execute
local-compose up -dto get the container(s) up and running. - Run anything with regular
docker compose ...syntax:local-compose exec ai claude --dangerously-skip-permissionslocal-compose exec ai bash
I use the following alias:
alias claude='eval "${CLAUDE_COMMAND:-local-compose exec ai claude --dangerously-skip-permissions}"This way, I get unrestricted claude in any directory and can also overwrite the command on by-project basis, by using direnv. For example: Sometimes I need to name my docker compose enviroment differently (-n name).
#!/usr/bin/env bash
set -euo pipefail
export BASE_DIR=$(dirname "$(readlink -f "$0")")
export COMPOSE_NAME=$(basename "$PWD" | tr -d '.')
export DOCKERFILE_PATH="$BASE_DIR/Dockerfile.local"
export COMPOSE_CONFIG_PATH="$BASE_DIR/docker-compose.local.yml"
if [ -f docker-compose.yml ]; then
export COMPOSE_PROJECT_OPTIONS="-f docker-compose.yml"
fi
exec docker compose --project-directory $PWD \
-p $COMPOSE_NAME \
-f $COMPOSE_CONFIG_PATH \
${COMPOSE_PROJECT_OPTIONS:-} \
"${@:-up}" FROM homebrew/brew:master
RUN sudo apt-get update && sudo apt-get install -y \
software-properties-common \
curl \
git \
libpq-dev \
gh \
jq
RUN brew update && brew install \
ruby \
node \
yarn \
golang \
kubectl \
helm \
stern \
rust \
crystal
RUN npm install -g @anthropic-ai/claude-code
RUN npm install -g @sourcegraph/amp
WORKDIR /home/linuxbrew/app---
services:
ai:
container_name: ${COMPOSE_PROJECT_NAME:-ai}
hostname: ${COMPOSE_PROJECT_NAME:-ai}
build:
context: .
dockerfile: ${DOCKERFILE_PATH:-Dockerfile.local}
volumes:
- .:/home/linuxbrew/app
- ~/.claude.json:/home/linuxbrew/.claude.json
- ~/.claude:/home/linuxbrew/.claude
- ~/.config/gh:/home/linuxbrew/.config/gh:ro
- ~/.config/amp:/home/linuxbrew/.config/amp
- ~/.local/share/amp:/home/linuxbrew/.local/share/amp
- ~/.local/state/amp:/home/linuxbrew/.local/state/amp
- ~/.cache/amp:/home/linuxbrew/.cache/amp
- ~/bin/:/home/linuxbrew/bin
tmpfs:
- /tmp:mode=1777
environment:
- RAILS_ENV=${RAILS_ENV:-development}
- DISABLE_SPRING=YES
command: /bin/bash
stdin_open: true
tty: true