186 lines
12 KiB
Docker
186 lines
12 KiB
Docker
# =============================================================================
|
|
# p0-7-Dockerfile — executable parity reconstruction of Anthropic's
|
|
# claude-code sandbox image ("container_01QJ16vmsgBTwzVoBf5YMxqf--wiggle--c916be").
|
|
#
|
|
# Evidence sources (all under /Users/kendallbooker/Downloads/container-exact):
|
|
# var/log/apt/history.log 100 apt transactions; the 5 tool-layer ones
|
|
# 2026-04-18 18:07:16 -> 18:12:26 replayed verbatim
|
|
# var/log/dpkg.log final installed set = 866 pkgs (base 92 + tool 774)
|
|
# var/log/bootstrap.log debootstrap noble 2026-04-10, mirror ftpmaster.internal
|
|
# etc/cloud/build.info build_name: ubuntu-oci:minimized / serial 20260410
|
|
# home/claude/.npm/_logs/2026-04-18T18_12_33_085Z-debug-0.log
|
|
# npm@10.9.7 / node v22.22.2 -g argv + registry traffic
|
|
# home/claude/.npm-global/... 21 top-level npm pkgs resolved (pinned below)
|
|
# usr/local/lib/python3.12/dist-packages/*.dist-info
|
|
# 114 uv-installed dists -> pinned uv stack below
|
|
# home/claude/.config/uv/uv-receipt.json
|
|
# uv 0.11.7, cargo-dist installer, ~/.local/bin
|
|
# usr/local/bin 3 custom ELF binaries + ~60 python console scripts
|
|
# etc/{hosts,machine-id,puppeteer-config.json}, usr/local/share/ca-certificates
|
|
#
|
|
# Drift note: built 2026-09 against live mirrors, not the April snapshot, so
|
|
# point-versions drift; see p0-7-build.md for the quantified delta.
|
|
# =============================================================================
|
|
|
|
FROM --platform=linux/amd64 ubuntu:24.04
|
|
|
|
ENV DEBIAN_FRONTEND=noninteractive
|
|
|
|
# ---- Layer 0: base parity -----------------------------------------------------
|
|
# Their base: debootstrap of noble serial 20260410 from ftpmaster.internal,
|
|
# then `dist-upgrade` + `install unminimize` (history.log lines 457-466).
|
|
# ubuntu:24.04:latest today is a newer serial -> acknowledged drift, unfixable
|
|
# without a digest pin.
|
|
COPY etc/cloud/build.info /etc/cloud/build.info
|
|
|
|
# ---- Layer 1: CA bundle staged + their txn 1 (curl ca-certificates) -----------
|
|
# Their 4 internal CAs are present before any update-ca-certificates run
|
|
# (usr/local/share/ca-certificates/*.crt, dropped 18:07 during build, imported
|
|
# at the 18:13 CA step). Fresh `apt-get update` first: their image had lists from
|
|
# the 20260410 base build; a 2026-09 rebuild must refresh against live mirrors.
|
|
COPY usr/local/share/ca-certificates/ /usr/local/share/ca-certificates/
|
|
RUN apt-get update
|
|
|
|
# (a) 18:07:16 -> 18:07:19 (17 pkgs; curl 8.5.0-2ubuntu10.8, ca-certs 20240203)
|
|
RUN apt-get install -y --no-install-recommends curl ca-certificates \
|
|
&& update-ca-certificates
|
|
# (b) 18:07:51 -> 18:07:52 (17 pkgs; gnupg 2.4.4-2ubuntu17.4, apt-transport-https 2.8.3)
|
|
RUN apt install -y apt-transport-https ca-certificates curl gnupg
|
|
|
|
# ---- Layer 2: nodesource repo (between txns 2 and 3; txn 3 pulls nodejs 22.x) --
|
|
# tx #3 installed nodejs 22.22.2-1nodesource1 from this repo; gpg+curl exist by now.
|
|
RUN mkdir -p /etc/apt/keyrings \
|
|
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
|
| gpg --dearmor -o /usr/share/keyrings/nodesource.gpg
|
|
COPY etc/apt/sources.list.d/nodesource.sources /etc/apt/sources.list.d/nodesource.sources
|
|
RUN apt-get update
|
|
|
|
# (c) 18:07:57 -> 18:08:00 (12 pkgs; nodejs 22.22.2-1nodesource1)
|
|
RUN apt-get install -y nodejs
|
|
# (d) 18:08:56 -> 18:10:53 (604 pkgs; texlive/libreoffice/ffmpeg/fonts/build stack)
|
|
RUN apt-get install -y --no-install-recommends wget fuse3 gnupg2 software-properties-common git graphviz build-essential zip unzip file bc netcat-openbsd libxml2-utils libnss3-tools p11-kit p11-kit-modules python3 python3-pip python3-dev python3-venv python3-wheel python3-uno pipx libcairo2-dev pkg-config libgl1 libglib2.0-0 default-jre-headless fonts-crosextra-carlito fonts-crosextra-caladea fonts-noto-cjk fonts-noto-cjk-extra fonts-dejavu fonts-liberation2 fonts-texgyre texlive-latex-base texlive-fonts-recommended texlive-latex-recommended texlive-xetex texlive-science texlive-pictures latexmk ffmpeg pandoc libreoffice-writer libreoffice-java-common ure-java poppler-utils qpdf imagemagick wkhtmltopdf tesseract-ocr tesseract-ocr-eng pdftk libreoffice-impress libreoffice-calc
|
|
# (e) 18:12:17 -> 18:12:26 (124 pkgs; headless-chromium runtime libs + xvfb + fonts)
|
|
RUN apt-get install -y --no-install-recommends libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0t64 libatspi2.0-0t64 libcairo2 libcups2t64 libdbus-1-3 libdrm2 libgbm1 libglib2.0-0t64 libnspr4 libnss3 libpango-1.0-0 libx11-6 libxcb1 libxcomposite1 libxdamage1 libxext6 libxfixes3 libxkbcommon0 libxrandr2 libcairo-gobject2 libfontconfig1 libfreetype6 libgdk-pixbuf-2.0-0 libgtk-3-0t64 libpangocairo-1.0-0 libx11-xcb1 libxcb-shm0 libxcursor1 libxi6 libxrender1 gstreamer1.0-libav gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good libicu74 libatomic1 libenchant-2-2 libepoxy0 libevent-2.1-7t64 libflite1 libgles2 libgstreamer-gl1.0-0 libgstreamer-plugins-bad1.0-0 libgstreamer-plugins-base1.0-0 libgstreamer1.0-0 libgtk-4-1 libharfbuzz-icu0 libharfbuzz0b libhyphen0 libjpeg-turbo8 liblcms2-2 libmanette-0.2-0 libopus0 libpng16-16t64 libsecret-1-0 libvpx9 libwayland-client0 libwayland-egl1 libwayland-server0 libwebp7 libwebpdemux2 libwoff1 libxml2 libxslt1.1 libx264-164 libavif16 xvfb fonts-noto-color-emoji fonts-unifont xfonts-cyrillic xfonts-scalable fonts-liberation fonts-ipafont-gothic fonts-wqy-zenhei fonts-tlwg-loma-otf fonts-freefont-ttf
|
|
|
|
# ---- Layer 4: the CA install step + dpkg trigger re-run (18:13:00/18:13:02) ----
|
|
# dpkg.log ends with two ca-certificates-java trigger passes at 18:13:00 and
|
|
# 18:13:02 — i.e. `update-ca-certificates` was run again after the java/p11-kit
|
|
# stack landed (their docker-entrypoint/CA-sync step). Re-run here for parity.
|
|
RUN update-ca-certificates && update-ca-certificates -f
|
|
|
|
# ---- Layer 5: uv toolchain + pinned Python stack -------------------------------
|
|
# uv 0.11.7 via cargo-dist installer into /home/claude/.local/bin (uv-receipt.json).
|
|
# 114 dists into /usr/local/lib/python3.12/dist-packages with `/usr/bin/python`
|
|
# resolved to /usr/bin/python3 (their shebangs are all #!/usr/bin/python) using
|
|
# uv pip install --system (INSTALLER=uv on all 114 dist-infos).
|
|
# Their index was https://artifactory.infra.ant.dev/artifactory/api/pypi/pypi-all
|
|
# (internal mirror of PyPI) -> public PyPI used here; pins are the dist-info versions.
|
|
RUN useradd -m -u 999 -s /bin/bash claude
|
|
COPY _context/uv_requirements.txt /tmp/uv_requirements.txt
|
|
USER claude
|
|
RUN curl -LsSf https://astral.sh/uv/0.11.7/install.sh | sh
|
|
ENV PATH="/home/claude/.local/bin:${PATH}"
|
|
USER root
|
|
# their /usr/bin/python -> python3 symlink is hand-made (no python-is-python3 pkg
|
|
# in dpkg.log); EXTERNALLY-MANAGED marker still present in snapshot -> they used
|
|
# --break-system-packages against the system interpreter.
|
|
RUN ln -sf /usr/bin/python3 /usr/bin/python \
|
|
&& uv pip install --python /usr/bin/python3 --system --break-system-packages -r /tmp/uv_requirements.txt
|
|
|
|
# ---- Layer 6: Node global prefix + pinned npm stack ----------------------------
|
|
# `npm i -g` as claude with prefix=/home/claude/.npm-global (home/claude/.npmrc).
|
|
# Log argv (2026-04-18T18:12:33.085Z, npm@10.9.7 / node v22.22.2):
|
|
# install --global graphviz @mermaid-js/mermaid-cli markdownlint-cli
|
|
# markdownlint-cli2 marked markdown-pdf markdown-toc remark-cli
|
|
# remark-preset-lint-recommended playwright@1.56.0 typescript tsx ts-node
|
|
# docx pdf-lib pdfjs-dist pptxgenjs react react-dom react-icons sharp
|
|
# Versions below are the RESOLVED versions read from
|
|
# home/claude/.npm-global/lib/node_modules/*/package.json (April 18).
|
|
COPY _context/npmrc /home/claude/.npmrc
|
|
USER claude
|
|
RUN npm install --global \
|
|
graphviz@0.0.9 \
|
|
@mermaid-js/mermaid-cli@11.12.0 \
|
|
markdownlint-cli@0.48.0 \
|
|
markdownlint-cli2@0.22.0 \
|
|
marked@18.0.2 \
|
|
markdown-pdf@11.0.0 \
|
|
markdown-toc@1.2.0 \
|
|
remark-cli@12.0.1 \
|
|
remark-preset-lint-recommended@7.0.1 \
|
|
playwright@1.56.0 \
|
|
typescript@6.0.3 \
|
|
tsx@4.21.0 \
|
|
ts-node@10.9.2 \
|
|
docx@9.6.1 \
|
|
pdf-lib@1.17.1 \
|
|
pdfjs-dist@5.6.205 \
|
|
pptxgenjs@4.0.1 \
|
|
react@19.2.5 \
|
|
react-dom@19.2.5 \
|
|
react-icons@5.6.0 \
|
|
sharp@0.34.5
|
|
USER root
|
|
|
|
# ---- Layer 7: Playwright browsers, pinned to build 1194 -------------------------
|
|
# opt/pw-browsers: chromium-1194, chromium_headless_shell-1194, ffmpeg-1011
|
|
# (PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers, from .npmrc/env).
|
|
# playwright@1.56.0 normally wants chromium-1200; their image force-installed the
|
|
# 1194 set -> same force here via PUPPETEER/PLAYWRIGHT env-free explicit install.
|
|
ENV PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers \
|
|
PATH="/home/claude/.local/bin:/home/claude/.npm-global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
RUN mkdir -p /opt/pw-browsers && chown claude:claude /opt/pw-browsers
|
|
USER claude
|
|
RUN playwright install chromium \
|
|
&& mkdir -p /opt/pw-browsers/chromium-1194 /opt/pw-browsers/chromium_headless_shell-1194 \
|
|
&& ( playwright install chromium@1194 chromium_headless_shell@1194 2>/dev/null \
|
|
|| echo 'WARN: pinned chromium-1194 revision not installable via playwright 1.56.0 CLI; default revision kept (see p0-7-build.md drift)' ) \
|
|
&& ls -la /opt/pw-browsers
|
|
USER root
|
|
# Also their puppeteer cache (Chrome 131.0.6778.204, used by markdown-pdf &
|
|
# mermaid-cli via puppeteer-config.json):
|
|
RUN chown -R claude:claude /home/claude/.cache || true
|
|
|
|
# ---- Layer 8: the 3 custom ELF binaries -----------------------------------------
|
|
# All x86-64 ELF, dropped in at 11:11-11:13 build time (not from apt/pip/npm):
|
|
# extract-text 2.0 MB stripped (Rust text-extraction CLI)
|
|
# magika 32 MB unstripped (Google magika standalone; pip magika 0.6.3 also present)
|
|
# rclone-filestore 29 MB stripped (Anthropic rclone fork; twin at /opt/rclone/)
|
|
COPY _context/bin/extract-text /usr/local/bin/extract-text
|
|
COPY _context/bin/magika /usr/local/bin/magika
|
|
COPY _context/bin/rclone-filestore /usr/local/bin/rclone-filestore
|
|
COPY _context/opt/rclone/rclone-filestore /opt/rclone/rclone-filestore
|
|
RUN chmod 755 /usr/local/bin/extract-text /usr/local/bin/magika /usr/local/bin/rclone-filestore \
|
|
&& mkdir -p /opt/rclone-attach
|
|
|
|
# ---- Layer 9: /etc edits ---------------------------------------------------------
|
|
# hosts: api.anthropic.com pinned to 160.79.104.10; runsc + vm blackholed to
|
|
# localhost (gVisor sandbox + metadata-service isolation).
|
|
COPY etc/hosts /etc/hosts
|
|
COPY etc/machine-id /etc/machine-id
|
|
COPY etc/puppeteer-config.json /etc/puppeteer-config.json
|
|
|
|
# ---- Layer 10: user/env finalization ---------------------------------------------
|
|
# /home/claude/.local/bin on PATH (uv installer modify_path=true)
|
|
RUN printf '%s\n' \
|
|
'export PATH="/home/claude/.local/bin:/home/claude/.npm-global/bin:/usr/local/bin:${PATH}"' \
|
|
'export PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers' \
|
|
'export PUPPETEER_CONFIG=/etc/puppeteer-config.json' \
|
|
'export NODE_PATH=/home/claude/.npm-global/lib/node_modules' \
|
|
> /etc/profile.d/claude-sandbox.sh \
|
|
&& chmod 644 /etc/profile.d/claude-sandbox.sh
|
|
|
|
ENV PATH="/home/claude/.local/bin:/home/claude/.npm-global/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
|
|
PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers \
|
|
PUPPETEER_CONFIG=/etc/puppeteer-config.json \
|
|
NODE_PATH=/home/claude/.npm-global/lib/node_modules
|
|
|
|
WORKDIR /home/claude
|
|
CMD ["/bin/bash"]
|
|
|
|
# --- additions for standalone use (original mounted these via squashfs) ---
|
|
COPY mnt-skills/ /mnt/skills/
|
|
RUN mkdir -p /mnt/user-data/uploads /mnt/user-data/outputs /mnt/transcripts /mnt/user-data/tool_results /tmp/rclone-mounts \
|
|
&& (id claude 2>/dev/null || groupadd -g 1001 claude; useradd -m -u 999 -g 1001 claude || true) \
|
|
&& printf 'IS_SANDBOX=yes\n' > /etc/sandbox-release
|