The Container class ↗ from @cloudflare/containers ↗ is the most common way to interact with container instances from a Worker.
Container extends DurableObject. The Durable Object manages routing, persistent state, and lifecycle hooks, while the container process runs your image inside a Linux VM. Because your subclass is a Durable Object, you have access to the full Durable Object API — including this.ctx.storage for persistent SQLite-backed storage and this.ctx.id for the unique instance identifier. Use Durable Object storage to persist state that should survive container restarts, such as configuration, user data, or task results.
npm i @cloudflare/containersyarn add @cloudflare/containerspnpm add @cloudflare/containersbun add @cloudflare/containersThen, define a class that extends Container and set the shared properties on the class:
import { Container, getContainer } from "@cloudflare/containers";
export class SandboxContainer extends Container {
defaultPort = 8080;
requiredPorts = [8080, 9222];
sleepAfter = "5m";
envVars = {
NODE_ENV: "production",
LOG_LEVEL: "info",
};
entrypoint = ["npm", "run", "start"];
enableInternet = false;
pingEndpoint = "localhost/ready";
}
export default {
async fetch(request, env) {
return getContainer(env.SANDBOX_CONTAINER, "workspace-123").fetch(request);
},
};import { Container, getContainer } from "@cloudflare/containers";
export class SandboxContainer extends Container {
defaultPort = 8080;
requiredPorts = [8080, 9222];
sleepAfter = "5m";
envVars = {
NODE_ENV: "production",
LOG_LEVEL: "info",
};
entrypoint = ["npm", "run", "start"];
enableInternet = false;
pingEndpoint = "localhost/ready";
}
export default {
async fetch(request: Request, env) {
return getContainer(env.SANDBOX_CONTAINER, "workspace-123").fetch(request);
},
};The Container class extends DurableObject, so all Durable Object functionality is available — including SQLite storage, alarms, and RPC methods. Container disk is ephemeral by default, but Durable Object storage persists across container restarts.
import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
defaultPort = 8080;
async runAndPersist() {
const res = await this.containerFetch("/run-task");
const body = await res.text();
this.ctx.storage.sql.exec(
"INSERT OR REPLACE INTO results (value) VALUES (?)",
body,
);
return body;
}
}import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
defaultPort = 8080;
async runAndPersist() {
const res = await this.containerFetch("/run-task");
const body = await res.text();
this.ctx.storage.sql.exec(
"INSERT OR REPLACE INTO results (value) VALUES (?)",
body,
);
return body;
}
}Use this.ctx.container.exec() to start another process inside a running Container. Refer to Execute commands for startup, streaming, output, and process-control examples.
Configure these as class fields on your subclass. They apply to every instance of the container.
-
defaultPort(number, optional) — the port your container process listens on.fetch()andcontainerFetch()forward requests here unless you specify a different port viaswitchPort()or theportargument tocontainerFetch(). Most subclasses set this. -
requiredPorts(number[], optional) — ports that must be accepting connections before the container is considered ready. Used bystartAndWaitForPorts()when noportsargument is passed. Set this when your container runs multiple services that all need to be healthy before serving traffic. -
sleepAfter(string | number, default:"10m") — how long to keep the container alive without activity before shutting it down. Accepts a number of seconds or a duration string such as"30s","5m", or"1h". Activity resets the timer — seerenewActivityTimeout()for manual resets. -
envVars(Record<string, string>, default:{}) — environment variables passed to the container on every start. For per-instance variables, passenvVarsthroughstartAndWaitForPorts()instead. -
entrypoint(string[], optional) — overrides the image's default entrypoint. Useful when you want to run a different command without rebuilding the image, such as a dev server or a one-off task. -
enableInternet(boolean, default:true) — controls whether the container can make outbound HTTP requests. Set tofalsefor sandboxed environments where you want to intercept or block all outbound traffic. For more information, refer to Handle outbound traffic. -
pingEndpoint(string, default:"ping") — the host and path the class uses to health-check the container during startup. Most users do not need to change this.
Override these methods to run Worker code when the container changes state. Refer to the status hooks example for a full example.
Run Worker code after the container has started.
onStart(): void | Promise<void>Returns: void | Promise<void>. Resolve after any startup logic finishes.
Use this to log startup, seed data, or schedule recurring tasks with schedule().
import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
defaultPort = 8080;
async onStart() {
await this.containerFetch("http://localhost/bootstrap", {
method: "POST",
});
}
}import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
defaultPort = 8080;
override async onStart() {
await this.containerFetch("http://localhost/bootstrap", {
method: "POST",
});
}
}Run Worker code after the container process exits.
onStop(params: StopParams): void | Promise<void>Parameters:
params.exitCode- Container process exit code.params.reason- Why the container stopped:'exit'when the process exited on its own, or'runtime_signal'when the runtime signalled it.
Returns: void | Promise<void>. Resolve after your shutdown logic finishes.
Use this to log, alert, or restart the container.
import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
onStop({ exitCode, reason }) {
console.log("Container stopped", { exitCode, reason });
}
}import { Container } from "@cloudflare/containers";
export class MyContainer extends Container {
override onStop({ exitCode, reason }) {
console.log("Container stopped", { exitCode, reason });
}
}Handle startup and port-checking errors.
onError(error: unknown): anyParameters:
error- The error thrown during startup or port checks.
Returns: any. The default implementation logs the error and re-throws it.
Override this to suppress errors, notify an external service, or attempt a restart.
import { Container } from "@cloudflare/containers";