-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile.base
More file actions
72 lines (55 loc) · 4.15 KB
/
Dockerfile.base
File metadata and controls
72 lines (55 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
FROM node:22-bookworm
ENV DEBIAN_FRONTEND=noninteractive
# ── System packages ──────────────────────────────────────────────────────────
RUN apt-get update && apt-get install -y --no-install-recommends \
curl wget gnupg2 ca-certificates lsb-release software-properties-common \
git jq zsh unzip zip sudo fzf ripgrep \
python3 python3-pip python3-venv pipx \
podman podman-compose fuse-overlayfs slirp4netns uidmap \
&& rm -rf /var/lib/apt/lists/*
# ── npm: disable postinstall scripts (supply-chain hardening) ───────────────
RUN npm config set ignore-scripts true --location=global
# ── Playwright (headless Chromium) ──────────────────────────────────────────
RUN npx --ignore-scripts=false playwright install --with-deps chromium
# ── Pre-fetch MCP server packages ───────────────────────────────────────────
RUN npx --yes --ignore-scripts=false @playwright/mcp@latest --help > /dev/null \
&& npx --yes --ignore-scripts=false @modelcontextprotocol/server-sequential-thinking --help > /dev/null
# ── git-delta (better diffs) ────────────────────────────────────────────────
ARG GIT_DELTA_VERSION=0.18.2
RUN ARCH=$(dpkg --print-architecture) \
&& wget -q "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" \
&& dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" \
&& rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb"
# ── Shell history (persisted via volume) ────────────────────────────────────
RUN mkdir -p /commandhistory && chmod 777 /commandhistory
ENV DEVCONTAINER=true
# ── Entrypoint (before USER switch, needs root for chmod) ───────────────────
COPY container/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# ── Non-root user (UID matches host user so mounted files are read/writable) ─
ARG HOST_UID=501
RUN useradd -m -s /bin/bash -G sudo -u ${HOST_UID} claude \
&& echo "claude ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
&& echo "claude:100000:65536" >> /etc/subuid \
&& echo "claude:100000:65536" >> /etc/subgid
# ── Everything below runs as claude user ────────────────────────────────────
USER claude
# Podman rootless config: vfs driver for maximum compatibility in nested containers
RUN mkdir -p ~/.config/containers \
&& printf '[storage]\ndriver = "vfs"\n' > ~/.config/containers/storage.conf
# Podman + Testcontainers: fixed socket path, disable Ryuk (incompatible with rootless Podman)
ENV XDG_RUNTIME_DIR=/run/podman-user
ENV DOCKER_HOST=unix:///run/podman-user/podman/podman.sock
ENV TESTCONTAINERS_RYUK_DISABLED=true
# ── Claude Code CLI (native installer) ──────────────────────────────────────
RUN curl -fsSL https://claude.ai/install.sh | bash
# ── uv / uvx (for Serena MCP) ──────────────────────────────────────────────
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/home/claude/.local/bin:${PATH}"
# ── Claude Code configuration ───────────────────────────────────────────────
COPY --chown=claude:claude container/claude-config.json /home/claude/.claude.json
# Container-specific instructions for Claude Code (renamed to CLAUDE.md by entrypoint)
RUN mkdir -p /home/claude/.claude-defaults
COPY --chown=claude:claude container/claude-container-instructions.md /home/claude/.claude-defaults/CLAUDE.md
WORKDIR /workspace
ENTRYPOINT ["/entrypoint.sh"]