-
Notifications
You must be signed in to change notification settings - Fork 115
Expand file tree
/
Copy pathDockerfile.sandbox
More file actions
107 lines (100 loc) · 7.03 KB
/
Copy pathDockerfile.sandbox
File metadata and controls
107 lines (100 loc) · 7.03 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# Guest image for the agent sandbox microVM (SANDBOX_IMAGE).
#
# node:24 is buildpack-deps based, so gcc/g++/make/ld/pkg-config, glib-2.0,
# git, ssh, python3, curl and wget are already present, but it ships no network
# diagnostics at all. This image adds the rest of the Manager image toolchain
# (pnpm, bun, uv, jq), the GitHub CLI, a Playwright-managed Chromium, the
# `python` alias, and the network tooling agents reach for.
FROM node:24
ARG PLAYWRIGHT_VERSION=1.56.0
# uv@latest (0.12.9) segfaults under qemu-user amd64 emulation, which is how
# cross-arch builds execute it; pin a known-good release and verify a bump.
ARG UV_VERSION=0.12.7
# Bump TOOLS_CACHEBUST (e.g. via --build-arg) to force a fresh tool install
# without invalidating the rest of the build cache.
ARG TOOLS_CACHEBUST=0
# Shared browser location so the sandbox exec user (SANDBOX_EXEC_USER, default
# "node") can read browsers installed at build time by root.
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# Lets agent code `require("playwright")` from any working directory without a
# project-local install. Only a resolution fallback; local node_modules wins.
ENV NODE_PATH=/usr/local/lib/node_modules
# msb exec runs commands as a numeric host uid with no /etc/passwd entry, so
# the guest defaults to HOME=/ and every tool that writes per-user state (uv
# and pip caches, git config, gh config, the pnpm store) fails with EACCES.
# Point HOME at a sticky world-writable directory and give corepack a shared
# prewarmed cache so the preinstalled pnpm resolves without network or root.
# PNPM_CONFIG_STORE_DIR pins the pnpm store to a container-internal path:
# pnpm 11 no longer reads npm_config_* env vars, and an unpinned store falls
# back into the bind-mounted project directory, where it floods the host file
# watcher and gets committed.
ENV HOME=/home/ocm-agent
ENV COREPACK_HOME=/usr/local/share/corepack
ENV UV_TOOL_BIN_DIR=/opt/agent-tools/bin
ENV PNPM_HOME=/opt/agent-tools
ENV PNPM_CONFIG_STORE_DIR=/home/ocm-agent/.local/share/pnpm/store
ENV PATH=/opt/agent-tools/bin:$PATH
RUN echo "Installing gh and CLI tooling (cachebust=${TOOLS_CACHEBUST})" && \
apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates curl gh jq less ripgrep sudo tree file procps \
python3-pip python3-venv python-is-python3 \
iproute2 iputils-ping bind9-dnsutils bind9-host net-tools \
netcat-openbsd traceroute lsof rsync && \
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
-o /usr/share/keyrings/githubcli-archive-keyring.gpg && \
chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
> /etc/apt/sources.list.d/github-cli.list && \
apt-get update && \
apt-get install -y --no-install-recommends gh && \
rm -rf /var/lib/apt/lists/* && \
rm -f /usr/lib/python3*/EXTERNALLY-MANAGED && \
printf 'Defaults env_keep += "npm_config_prefix"\nALL ALL=(ALL:ALL) NOPASSWD:ALL\n' \
> /etc/sudoers.d/ocm-guest && \
chmod 440 /etc/sudoers.d/ocm-guest && \
visudo -c && \
gh --version
# corepack prepare runs as root and creates COREPACK_HOME/v1 and
# lastKnownGood.json beneath the sticky top-level directory, so those must be
# opened up afterwards or a project pinning any other packageManager version
# fails with "Failed to create cache directory" for the exec user.
RUN echo "Installing pnpm, bun and uv (cachebust=${TOOLS_CACHEBUST})" && \
mkdir -p /home/ocm-agent /opt/agent-tools/bin /usr/local/share/corepack && \
chmod 1777 /home/ocm-agent /opt/agent-tools /opt/agent-tools/bin /usr/local/share/corepack && \
corepack enable && corepack prepare pnpm@latest --activate && \
find /usr/local/share/corepack -type d -exec chmod 1777 {} + && \
chmod a+rw /usr/local/share/corepack/lastKnownGood.json && \
curl -fsSL https://bun.sh/install | BUN_INSTALL=/opt/bun bash && \
chmod -R a+rX /opt/bun && \
ln -sf /opt/bun/bin/bun /opt/bun/bin/bunx && \
ln -s /opt/bun/bin/bun /usr/local/bin/bun && \
ln -s /opt/bun/bin/bun /usr/local/bin/bunx && \
curl -LsSf https://astral.sh/uv/${UV_VERSION}/install.sh | UV_INSTALL_DIR=/usr/local/bin UV_NO_MODIFY_PATH=1 sh && \
rm -rf /root/.npm /root/.cache/uv /home/ocm-agent/.cache && \
pnpm --version && bun --version && uv --version
RUN echo "Installing playwright=${PLAYWRIGHT_VERSION} chromium (cachebust=${TOOLS_CACHEBUST})" && \
npm install -g "playwright@${PLAYWRIGHT_VERSION}" && \
npx --yes "playwright@${PLAYWRIGHT_VERSION}" install --with-deps chromium && \
chmod -R a+rX "${PLAYWRIGHT_BROWSERS_PATH}" && \
rm -rf /var/lib/apt/lists/* /root/.npm && \
npx --yes "playwright@${PLAYWRIGHT_VERSION}" --version
# Declared after the Playwright layer on purpose: npm_config_prefix must not
# affect the root-run `npm install -g playwright`, which has to land in
# /usr/local/lib/node_modules for the NODE_PATH fallback above to work.
ENV npm_config_prefix=/opt/agent-tools
# The runtime exec user is a numeric host uid with no /etc/passwd entry, so the
# toolchain is verified as uid 4242, which is absent from this image's passwd
# database. uid 1000 would not do: it is the base image's `node` user, so it
# would exercise the known-user path and pass even if the real one were broken.
# sudo is checked separately as that known user, because sudo refuses unknown
# uids by design and the Manager provisions their passwd entry at runtime.
RUN echo "Verifying guest toolchain as an unknown uid (cachebust=${TOOLS_CACHEBUST})" && \
rm -rf /home/ocm-agent && \
mkdir -p /home/ocm-agent && \
chmod 1777 /home/ocm-agent && \
setpriv --reuid=4242 --regid=4242 --clear-groups sh -c "set -e; pnpm --version; mkdir /tmp/pm-pin-check && cd /tmp/pm-pin-check && printf '{\"name\":\"pm-pin-check\",\"packageManager\":\"pnpm@10.12.1\"}' > package.json && pnpm --version | grep -qx 10.12.1 && cd / && rm -rf /tmp/pm-pin-check; bun --version; bunx --version; uv --version; uvx --version; playwright --version; gh --version; jq --version; rg --version; npm install -g --silent cowsay && cowsay -t verify-ok | head -1; git config --global user.email verify@ocm.local; uv venv /tmp/uv-check >/dev/null; uv pip install --python /tmp/uv-check/bin/python idna >/dev/null; pip3 install --user --force-reinstall --no-deps --quiet idna; rm -rf /tmp/uv-check; for tool in python python3 git curl wget ssh rsync lsof ip ss netstat ping dig host nslookup nc traceroute; do command -v \"\$tool\" >/dev/null || { echo \"missing guest tool: \$tool\"; exit 1; }; done; python --version" && \
setpriv --reuid=1000 --regid=1000 --clear-groups sh -c "set -e; sudo -n apt-get update -qq; sudo -n apt-get install -y -qq --no-install-recommends bc; bc --version | head -1" && \
rm -rf /home/ocm-agent /opt/agent-tools /var/lib/apt/lists/* /usr/local/share/corepack/v1/pnpm/10.12.1 && \
mkdir -p /home/ocm-agent /opt/agent-tools/bin && \
chmod 1777 /home/ocm-agent /opt/agent-tools /opt/agent-tools/bin