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:
|
Three containers managed by Docker Compose:
|
||||||
|
|
||||||
- **`claude`** — Claude Code CLI (`node:20-alpine`), non-root (UID 1000), isolated to an internal-only Docker network
|
- **`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`), non-root (UID 1000), same network isolation, basic auth required
|
- **`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
|
- **`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.
|
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
|
- **`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`), UID 1000, on `claude-internal` only, port 7681
|
- **`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
|
- **`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
|
- **`claude-internal`** — `internal: true`; no default gateway, containers cannot reach the internet directly
|
||||||
- **`proxy-external`** — Standard bridge; proxy sidecar only
|
- **`proxy-external`** — Standard bridge; proxy sidecar only
|
||||||
|
|
@ -161,7 +161,7 @@ Rebuild after changes:
|
||||||
|
|
||||||
| Control | claude / webui | proxy |
|
| 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 |
|
| `no-new-privileges` | yes | yes |
|
||||||
| All capabilities dropped | yes | yes |
|
| All capabilities dropped | yes | yes |
|
||||||
| Direct internet access | no (`internal` network only) | allowlisted only |
|
| 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)
|
# Entrypoint used by the webui service (ttyd wrapping claude)
|
||||||
COPY --chmod=755 webui-entrypoint.sh /usr/local/bin/webui-entrypoint.sh
|
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)
|
# Install Claude Code globally
|
||||||
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)
|
|
||||||
RUN npm install -g @anthropic-ai/claude-code
|
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
|
# Pre-creating ~/.claude ensures the named volume is initialised with the
|
||||||
# correct ownership when first mounted (Docker copies image content into
|
# correct ownership when first mounted (Docker copies image content into
|
||||||
# an empty named volume on first use).
|
# an empty named volume on first use).
|
||||||
RUN mkdir -p /workspace /home/claude/.claude \
|
RUN mkdir -p /workspace /home/node/.claude \
|
||||||
&& chown -R claude:claude /workspace /home/claude/.claude
|
&& chown -R node:node /workspace /home/node/.claude
|
||||||
|
|
||||||
USER claude
|
USER node
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|
||||||
# Proxy traffic through sidecar — override at runtime if needed
|
# Proxy traffic through sidecar — override at runtime if needed
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ services:
|
||||||
# OAuth callback — required for browser-based login (claude login)
|
# OAuth callback — required for browser-based login (claude login)
|
||||||
- "0.0.0.0:54545:54545"
|
- "0.0.0.0:54545:54545"
|
||||||
volumes:
|
volumes:
|
||||||
- claude-config:/home/claude/.claude
|
- claude-config:/home/node/.claude
|
||||||
# Workspace is injected by claude.sh via --volume flag at run time.
|
# Workspace is injected by claude.sh via --volume flag at run time.
|
||||||
# Default: named Docker volume. Override: set WORKSPACE_DIR on the host.
|
# Default: named Docker volume. Override: set WORKSPACE_DIR on the host.
|
||||||
security_opt:
|
security_opt:
|
||||||
|
|
@ -82,7 +82,7 @@ services:
|
||||||
# OAuth callback — required for browser-based login (claude login)
|
# OAuth callback — required for browser-based login (claude login)
|
||||||
- "0.0.0.0:54545:54545"
|
- "0.0.0.0:54545:54545"
|
||||||
volumes:
|
volumes:
|
||||||
- claude-config:/home/claude/.claude
|
- claude-config:/home/node/.claude
|
||||||
- claude-web-workspace:/workspace
|
- claude-web-workspace:/workspace
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue