-
Notifications
You must be signed in to change notification settings - Fork 629
Expand file tree
/
Copy pathDockerfile
More file actions
116 lines (107 loc) · 5.45 KB
/
Copy pathDockerfile
File metadata and controls
116 lines (107 loc) · 5.45 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
108
109
110
111
112
113
114
115
116
# Sandbox container image for the think agent.
#
# Pulls the prebuilt wsd SEA binary out of the public GHCR image published by
# github.com/cloudflare/workspace. The image is pinned separately from the host
# package and only needs to move when the workspace RPC / wsd wire changes.
# wsd runs as PID 1 and serves the workspace RPC + FUSE mount.
#
# Layered on top: a Node.js + Bun toolchain (node, npm, bun, esbuild,
# wrangler) plus git / gh / curl so `exec` calls from the agent find
# them on PATH inside the FUSE-mounted /workspace. The image stays
# otherwise lean.
# Workspace PR #18, commit 98b74eb. Keep this in sync with the
# @cloudflare/workspace pkg.pr.new dependency in package.json.
FROM ghcr.io/cloudflare/workspace-wsd-linux-x64:pr-18-98b74eb@sha256:179a3dc35bdf752d4cdcef07012dcf5c9949d04ba4d0d3ab1ed6d5703cfd73a9 AS wsd
FROM debian:stable-slim
# Base toolchain + FUSE runtime.
#
# Everything here comes from Debian's own apt (HTTP transport + GPG-signed
# packages), so the build has NO HTTPS fetch that a TLS-inspecting proxy
# (Cloudflare WARP) would break. `gh` ships in Debian bookworm `main`, so
# there is no need to add GitHub's own HTTPS apt repo (which WARP *would*
# break) — we deliberately install the distro `gh` instead.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates curl xz-utils git bash unzip \
fuse3 libfuse2t64 \
build-essential python3 \
gh jq \
&& rm -rf /var/lib/apt/lists/*
# Optional WARP / corporate-MITM CA bundle.
#
# When the host runs behind Cloudflare WARP (or any other decrypting
# TLS proxy), the certificates the public CA bundle trusts are
# replaced with WARP's own roots. `curl`, `npm install`, `bun install`,
# etc. inside the build then fail with "unable to get local issuer
# certificate" the first time they touch an external HTTPS endpoint.
#
# The fix is to drop the WARP root bundle at `ca/warp-ca.crt`
# (gitignored — host-specific) before the build. The `ca/` directory
# itself is committed with a `.keep` so the `COPY` below always has
# at least one source; when no real CA file is present, the conditional
# `update-ca-certificates` is a no-op and the build behaves identically.
#
# Hosts without WARP just don't drop the file and pay zero cost. Note the
# build context is the app dir, so the COPY source is `ca/`.
COPY ca/ /opt/agent-ca/
RUN if ls /opt/agent-ca/*.crt >/dev/null 2>&1; then \
cp /opt/agent-ca/*.crt /usr/local/share/ca-certificates/ \
&& update-ca-certificates ; \
fi \
&& rm -rf /opt/agent-ca
# wsd binary. Statically linked SEA, no external deps needed.
COPY --from=wsd /usr/local/bin/wsd /usr/local/bin/wsd
# Project-specific toolchain. The agent's `exec` tool finds these
# CLIs on PATH inside the FUSE-mounted /workspace.
#
# TLS trust under Cloudflare WARP (or any decrypting corporate proxy):
# when the host CA bundle has been merged with WARP's root via the
# COPY + `update-ca-certificates` step above, every TLS client inside
# the container needs to find the bundle. Each ecosystem has its own
# env var:
#
# - SSL_CERT_FILE — OpenSSL fallback. Curl, git, native libs,
# and most language runtimes honour this.
# - NODE_EXTRA_CA_CERTS — Node's TLS stack. Appends to its bundled
# CA list (not a replacement).
# - REQUESTS_CA_BUNDLE — Python's `requests`. Keeps Python add-ons
# and `pip` calls made through `exec` on the
# same trusted bundle.
#
# Setting all three before the Node/Bun install means the global
# `npm install -g esbuild wrangler` and Bun bootstrap below also run
# through the trusted bundle — npm shells out to curl for some downloads
# and Node directly for others, so both env vars matter at install time,
# not just at agent runtime. See ca/ for the file the host-side WARP
# bundle drops into.
ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
ENV REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
# Node.js 24 (Active LTS), Bun, TypeScript / Cloudflare Worker toolchain.
# Debian's `nodejs` package version moves with the base image; install the
# official binary tarball so shells inside the workspace consistently see
# Node 24. 24.x ships `node:sqlite` without the --experimental-sqlite
# flag (still RC, but importable as-is) and is the current Active LTS
# that the Cloudflare Workers runtime aligns against.
RUN NODE_VERSION=24.16.0 && \
curl -fsSL --cacert /etc/ssl/certs/ca-certificates.crt \
https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz \
| tar -xJ -C /usr/local --strip-components=1 && \
node --version && npm --version && \
npm install -g esbuild@0.25.0 wrangler@4 pnpm@10 && \
BUN_VERSION=1.2.23 && \
curl -fsSL --cacert /etc/ssl/certs/ca-certificates.crt https://bun.sh/install \
| bash -s "bun-v${BUN_VERSION}" && \
ln -s /root/.bun/bin/bun /usr/local/bin/bun && \
ln -s /root/.bun/bin/bunx /usr/local/bin/bunx && \
bun --version && bunx --version
# wsd configuration. PORT and MOUNT_POINT are the defaults the
# CloudflareContainerBackend expects. FUSE_MOUNT=auto probes
# /dev/fuse at startup: real FUSE under Cloudflare Containers,
# userspace shim when /dev/fuse isn't passed through (wrangler dev
# on macOS, CI without CAP_SYS_ADMIN). Same image works in both.
ENV PORT=8080
ENV MOUNT_POINT=/workspace
ENV FUSE_MOUNT=auto
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/wsd"]