Important
This example uses experimental parts of Cloudflare Computer: the container backend and computerd.
Their APIs may change in any release, and they are not yet suitable
for production use. See the
status table.
A Cloudflare Worker + Durable Object that boots a Container running the
computerd daemon and exposes a minimal write / read / exec HTTP
surface.
Declare the available images in wrangler.jsonc. Wrangler prepares each
image and exposes it through ctx.container.images:
Select the image when you create the backend:
new ContainerBackend({
container: () => this,
workspace: { binding: "ContainerExample", id: this.ctx.id.toString() },
name: "app", // the images key above; "app" is the default
});Set the instance size on the backend:
new ContainerBackend({
// ...
instance: "standard-2",
});The containers entry accepts these fields:
| Field | Purpose |
|---|---|
name |
Names the container application. |
class_name |
Names the Durable Object class that owns the container. |
scheduling_policy |
Set to "durable_object" so each Durable Object manages its container. |
images |
Declares the named images available through ctx.container.images. |
observability |
Configures logging for the container application. |
unsafe |
Holds restricted experimental settings. |
client ββΊ Worker /c/<name>/{file,exec}
β (DO RPC calls)
βΌ
DO (ContainerExample) βββΊ Container βββΊ computerd (:8080)
β² β
β ws://computer.internal/api β
βββββββββββ capnweb session ββββββββ
- The DO constructs a
ContainerBackendand hands it to aWorkspace. The backend owns the computerd lifecycle: it starts the container with the image and size above, wires egress, probes/health, and asks computerd to dial back. - computerd's outbound
/apiupgrade is intercepted by the egress and lands on the DO'sfetch, which forwards it tobackend.handleFetch. - The resulting capnweb session carries filesystem sync and
exec.
If a container fails its startup health check, the replacement uses the same image and instance size.
src/skills/exec/SKILL.md explains how exec works on this backend,
for an agent working in the workspace. It ships inside the Worker
upload through the find_additional_modules rule in wrangler.jsonc,
and WorkerBundle("skills") copies it to /workspace/.agents/skills
as a read-only mount. When a deploy changes the file, each workspace
picks up the new copy on its next start. The mount reaches the container
through the normal sync, like any other workspace file.
curl -X POST -H 'content-type: application/json' \
-d '{"command":"cat /workspace/.agents/skills/exec/SKILL.md"}' \
http://localhost:8787/c/demo/execnpm run dev --workspace @example/computer-container# write a file into the workspace
curl -X PUT --data 'hello' \
http://localhost:8787/c/demo/file/workspace/hello.txt
# read it back
curl http://localhost:8787/c/demo/file/workspace/hello.txt
# run a command against it
curl -X POST -H 'content-type: application/json' \
-d '{"command":"cat /workspace/hello.txt"}' \
http://localhost:8787/c/demo/execLocal development needs Docker. wrangler dev builds the image and runs it
against the local daemon.