refactor(claude): use built-in node user instead of custom claude user
Drop the addgroup/adduser layer entirely. node:20-alpine already ships a node user at uid/gid 1000. Update chown and USER directives, and update the claude-config volume mount path to /home/node/.claude.
This commit is contained in:
parent
0800e4a084
commit
1c489f8636
4 changed files with 12 additions and 16 deletions
|
|
@ -10,8 +10,8 @@ This file provides context and guidance for working with this project.
|
|||
|
||||
Three containers managed by Docker Compose:
|
||||
|
||||
- **`claude`** — Claude Code CLI (`node:20-alpine`), non-root (UID 1000), isolated to an internal-only Docker network
|
||||
- **`webui`** — Claude Code as a browser terminal via ttyd (`node:20-alpine`), non-root (UID 1000), same network isolation, basic auth required
|
||||
- **`claude`** — Claude Code CLI (`node:20-alpine`), runs as the built-in `node` user (UID 1000), isolated to an internal-only Docker network
|
||||
- **`webui`** — Claude Code as a browser terminal via ttyd (`node:20-alpine`), `node` user (UID 1000), same network isolation, basic auth required
|
||||
- **`proxy`** — Squid forward proxy (`alpine:3.21`), `squid` user, bridges the internal network to the internet with an egress allowlist
|
||||
|
||||
Key Docker network property: `claude-internal` has `internal: true`, meaning Docker adds no default gateway. The `claude` and `webui` containers physically cannot reach the internet without going through the `proxy` container.
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ Runs [Claude Code](https://claude.ai/code) inside an isolated Docker environment
|
|||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **`claude`** — Claude Code CLI (`node:20-alpine`), UID 1000, on `claude-internal` only
|
||||
- **`webui`** — Claude Code in a browser terminal via ttyd (`node:20-alpine`), UID 1000, on `claude-internal` only, port 7681
|
||||
- **`claude`** — Claude Code CLI (`node:20-alpine`), runs as the built-in `node` user (UID 1000), on `claude-internal` only
|
||||
- **`webui`** — Claude Code in a browser terminal via ttyd (`node:20-alpine`), `node` user (UID 1000), on `claude-internal` only, port 7681
|
||||
- **`proxy`** — Squid forward proxy (`alpine:3.21`), bridges `claude-internal` ↔ internet with egress allowlist
|
||||
- **`claude-internal`** — `internal: true`; no default gateway, containers cannot reach the internet directly
|
||||
- **`proxy-external`** — Standard bridge; proxy sidecar only
|
||||
|
|
@ -161,7 +161,7 @@ Rebuild after changes:
|
|||
|
||||
| Control | claude / webui | proxy |
|
||||
|---|---|---|
|
||||
| Non-root user | UID 1000 (`claude`) | `squid` user |
|
||||
| Non-root user | UID 1000 (`node`, built into base image) | `squid` user |
|
||||
| `no-new-privileges` | yes | yes |
|
||||
| All capabilities dropped | yes | yes |
|
||||
| Direct internet access | no (`internal` network only) | allowlisted only |
|
||||
|
|
|
|||
|
|
@ -11,21 +11,17 @@ RUN apk add --no-cache \
|
|||
# Entrypoint used by the webui service (ttyd wrapping claude)
|
||||
COPY --chmod=755 webui-entrypoint.sh /usr/local/bin/webui-entrypoint.sh
|
||||
|
||||
# Create non-root user (node:20-alpine reserves gid/uid 1000 for the node user)
|
||||
RUN addgroup -g 1001 claude \
|
||||
&& adduser -u 1001 -G claude -s /bin/bash -D claude
|
||||
|
||||
# Install Claude Code globally (runs as root for npm -g, then drops)
|
||||
# Install Claude Code globally
|
||||
RUN npm install -g @anthropic-ai/claude-code
|
||||
|
||||
# Workspace and Claude config dir — both owned by claude user.
|
||||
# Workspace and Claude config dir — owned by the built-in node user (uid 1000).
|
||||
# Pre-creating ~/.claude ensures the named volume is initialised with the
|
||||
# correct ownership when first mounted (Docker copies image content into
|
||||
# an empty named volume on first use).
|
||||
RUN mkdir -p /workspace /home/claude/.claude \
|
||||
&& chown -R claude:claude /workspace /home/claude/.claude
|
||||
RUN mkdir -p /workspace /home/node/.claude \
|
||||
&& chown -R node:node /workspace /home/node/.claude
|
||||
|
||||
USER claude
|
||||
USER node
|
||||
WORKDIR /workspace
|
||||
|
||||
# Proxy traffic through sidecar — override at runtime if needed
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ services:
|
|||
# OAuth callback — required for browser-based login (claude login)
|
||||
- "0.0.0.0:54545:54545"
|
||||
volumes:
|
||||
- claude-config:/home/claude/.claude
|
||||
- claude-config:/home/node/.claude
|
||||
# Workspace is injected by claude.sh via --volume flag at run time.
|
||||
# Default: named Docker volume. Override: set WORKSPACE_DIR on the host.
|
||||
security_opt:
|
||||
|
|
@ -82,7 +82,7 @@ services:
|
|||
# OAuth callback — required for browser-based login (claude login)
|
||||
- "0.0.0.0:54545:54545"
|
||||
volumes:
|
||||
- claude-config:/home/claude/.claude
|
||||
- claude-config:/home/node/.claude
|
||||
- claude-web-workspace:/workspace
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue