3.9 KiB
Dockerfile Notes
Base image
FROM node:24-bookworm-slim
Uses the official Node.js 24 image on Debian Bookworm (slim variant). Node.js is required because claude is a Node.js application distributed as a self-contained binary.
The slim variant strips documentation and locale files to keep the image small, while still including everything needed to run Node apps.
Note: This image ships with a node user and node group, both at UID/GID 1000. This is a convention in official Docker images — providing a ready-made unprivileged user so containers don't run as root by default. We replace this user with claude (see below).
System packages
RUN apt-get update && apt-get install -y \
git curl wget jq netcat-openbsd socat \
iputils-ping iproute2 dnsutils python3 \
unzip zstd procps lsof psmisc \
&& rm -rf /var/lib/apt/lists/*
Tools installed for use inside the container:
| Package | Purpose |
|---|---|
git |
Version control |
curl, wget |
HTTP requests / file downloads |
jq |
JSON processing on the command line |
netcat-openbsd |
TCP/UDP connection testing (nc) |
socat |
Multipurpose socket relay |
iputils-ping |
ping command |
iproute2 |
ip command, network inspection |
dnsutils |
dig, nslookup |
python3 |
Scripting |
unzip |
Zip archive extraction |
zstd |
Zstandard compression/decompression |
procps |
ps, top, process inspection |
lsof |
List open files / sockets |
psmisc |
fuser, killall, pstree |
The rm -rf /var/lib/apt/lists/* at the end discards the apt package index so it doesn't bloat the image layer.
UID/GID build args
ARG UID=1000
ARG GID=1000
Build-time arguments that control which UID and GID the claude user gets inside the container. The defaults are 1000/1000 (the most common primary user on Linux desktops).
The purpose is to match the host system's user, so that files written inside the container (e.g. in a mounted workspace volume) are owned by the correct user on the host — avoiding permission issues.
Pass these at build time to override:
docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) .
Claude binary installation
RUN GCS="https://storage.googleapis.com/..." \
&& VERSION=$(curl -fsSL "$GCS/latest") \
&& CHECKSUM=$(curl -fsSL "$GCS/$VERSION/manifest.json" | jq -r '.platforms["linux-x64"].checksum') \
&& curl -fsSL "$GCS/$VERSION/linux-x64/claude" -o /tmp/claude \
&& echo "$CHECKSUM /tmp/claude" | sha256sum -c \
&& mv /tmp/claude /usr/local/bin/claude \
&& chmod +x /usr/local/bin/claude
Downloads the latest claude release from Google Cloud Storage:
- Fetches the current version string from
latest - Fetches the expected SHA-256 checksum from
manifest.json - Downloads the
linux-x64binary to/tmp/claude - Verifies the checksum before installing — build fails if it doesn't match
- Moves the binary to
/usr/local/bin/claudeand makes it executable
User setup
RUN userdel node && groupdel node \
&& groupadd -g $GID claude \
&& useradd -u $UID -g $GID -m -s /bin/bash claude
USER claude
The base image's node user and group are removed first to free up UID/GID 1000 (or whatever was passed in). A claude user and group are then created in their place.
-mcreates a home directory at/home/claude-s /bin/bashsets bash as the login shellUSER claudeswitches all subsequent instructions (and the running container) to this unprivileged user
Workspace and entrypoint
WORKDIR /workspace
CMD ["claude"]
/workspace is the default working directory — intended to be bind-mounted from the host:
docker run -it -v "$PWD:/workspace" claude-image
CMD ["claude"] launches the Claude Code CLI when the container starts.