Container Echo
Echo a message via Cloudflare Containers backed by a Durable Object
Echo a message through Cloudflare Containers. A Durable Object subclass (EchoContainer) extends @cloudflare/containers's Container and proxies requests to a Node HTTP server running in the container image.
API Reference
POST /echo
Send text/plain or JSON ({ "message": "..." } or { "echo": "..." }).
Body must be non-empty and at most 10,000 characters.
Example Request
curl -X POST "https://your-worker.workers.dev/echo" \
-H "Content-Type: application/json" \
-d '{"message":"hello"}'Success Response
{
"echo": "hello",
"port": 8080
}Error Codes
400- Invalid or empty body (INVALID_BODY)502- Container or proxy failure (ECHO_ERROR)
Use Cases
- Learn Containers + Durable Object lifecycle with a minimal API
- Prototype Worker-to-container request forwarding
- Validate Dockerfile-backed images on Cloudflare
- Compare Containers vs pure Workers for Node-style servers
Limitations
- Docker must be available for
wrangler dev/ deploy image builds - Message body capped at 10,000 characters
- Demo exposes a single echo path; not a general proxy
- Container instances are limited (
max_instances: 2in wrangler)
Use in your project
Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/container-echo.
import type { Env } from "../types/env";import type { EchoResult } from "../types/echo";const INSTANCE_NAME = "default";export function getEchoStub(env: Env): DurableObjectStub { if (typeof env.ECHO.getByName === "function") { return env.ECHO.getByName(INSTANCE_NAME); } const id = env.ECHO.idFromName(INSTANCE_NAME); return env.ECHO.get(id);}export async function echoMessage(env: Env, message: string): Promise<EchoResult> { const stub = getEchoStub(env); const response = await stub.fetch("https://echo/echo", { method: "POST", headers: { "Content-Type": "text/plain" }, body: message, }); if (!response.ok) { throw new Error(`Container echo failed with status ${response.status}`); } return (await response.json()) as EchoResult;}export function validateMessage(input: string | undefined | null): string | null { if (typeof input !== "string") return null; if (input.length === 0 || input.length > 10_000) return null; return input;}Deployment
Deploy
Wrangler builds ./Dockerfile, registers the EchoContainer Durable Object, and binds it as ECHO.
Test your deployment
curl -X POST "https://your-worker.workers.dev/echo" \
-H "Content-Type: text/plain" \
-d "hello"Local Development
Docker must be running for container image builds.
cd apps/experiments/container-echo
npm install
npm run devcurl -X POST "http://localhost:8787/echo" \
-H "Content-Type: application/json" \
-d '{"message":"hello"}'Unit tests mock the Durable Object binding so Docker is not required for npm run test.
Configuration
wrangler.json declares:
- Container
EchoContainerfrom./Dockerfile(port 8080) - Durable Object binding
ECHO→EchoContainer - Migration
v1withnew_sqlite_classes: ["EchoContainer"]
Cloudflare Features Used
- Workers - Edge compute runtime
- Containers - Dockerfile-backed runtime on Cloudflare
- Durable Objects - Container lifecycle via
@cloudflare/containers