Skip to content

Container Interface

Last updated View as MarkdownAgent setup

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/containers

Then, 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;
	}
}

Execute commands

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.

Properties

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() and containerFetch() forward requests here unless you specify a different port via switchPort() or the port argument to containerFetch(). Most subclasses set this.

  • requiredPorts (number[], optional) — ports that must be accepting connections before the container is considered ready. Used by startAndWaitForPorts() when no ports argument 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 — see renewActivityTimeout() for manual resets.

  • envVars (Record<string, string>, default: {}) — environment variables passed to the container on every start. For per-instance variables, pass envVars through startAndWaitForPorts() 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 to false for 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.

Lifecycle hooks

Override these methods to run Worker code when the container changes state. Refer to the status hooks example for a full example.

onStart

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",
    	});
    }

}

onStop

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 });
	}
}

onError

Handle startup and port-checking errors.

onError(error: unknown): any

Parameters:

  • 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";