Containers

Last updated Oct 12, 2026 Enhance your Workers with serverless containers

Available on Workers Paid plan

Run code written in any programming language, built for any runtime, as part of apps built on Workers.

Deploy your container image to Region:Earth without worrying about managing infrastructure - just define your Worker and wrangler deploy.

With Containers you can run:

  • Resource-intensive applications that require CPU cores running in parallel, large amounts of memory or disk space
  • Applications and libraries that require a full filesystem, specific runtime, or Linux-like environment
  • Existing applications and tools that have been distributed as container images

Container instances are spun up on-demand and controlled by code you write in your Worker. Instead of chaining together API calls or writing Kubernetes operators, you just write TypeScript or JavaScript.

src/index.jsjs

import { DurableObject } from "cloudflare:workers";
import { rewriteRequestForContainer, startAndWaitForPort } from "./utils";

export class MyContainer extends DurableObject {
    async fetch(request) {
        const container = this.ctx.container;
        await startAndWaitForPort(container, {
            port: 4000,
            inactivityTimeout: 10 * 60 * 1000,
        });

        const forwarded = rewriteRequestForContainer(request);
        const response = await container.getTcpPort(4000).fetch(forwarded);
        return response;
    }
}

export default {
    async fetch(request, env) {
        const containerRequest = request.clone();
        const { "session-id": sessionId } = await request.json();
        return env.MY_CONTAINER.getByName(sessionId).fetch(containerRequest);
    },
};

src/index.tsts

import { DurableObject } from "cloudflare:workers";
import { rewriteRequestForContainer, startAndWaitForPort } from "./utils";

interface Env {
    MY_CONTAINER: DurableObjectNamespace<MyContainer>;
}

export class MyContainer extends DurableObject<Env> {
    async fetch(request: Request): Promise<Response> {
        const container = this.ctx.container!;
        await startAndWaitForPort(container, {
            port: 4000,
            inactivityTimeout: 10 * 60 * 1000,
        });

        const forwarded = rewriteRequestForContainer(request);
        const response = await container.getTcpPort(4000).fetch(forwarded);
        return response;
    }
}

export default {
    async fetch(request: Request, env: Env): Promise<Response> {
        const containerRequest = request.clone();
        const { "session-id": sessionId } = await request.json<{
            "session-id": string;
        }>();
        return env.MY_CONTAINER.getByName(sessionId).fetch(containerRequest);
    },
};

src/utils.jsjs

export function rewriteRequestForContainer(request) {
    const url = new URL(request.url);
    url.protocol = "http:";
    url.host = "container";
    const forwarded = new Request(url, request);
    forwarded.headers.delete("host");
    return forwarded;
}

export async function startAndWaitForPort(container, options) {
    await container.setInactivityTimeout(options.inactivityTimeout);
    if (!container.running) {
        container.start();
    }

    // start() returns before the container is ready, so poll its health endpoint.
    const port = container.getTcpPort(options.port);
    let lastError;
    for (let attempt = 0; attempt < 100; attempt++) {
        try {
            const response = await port.fetch("http://container/health");
            if (!response.ok) {
                throw new Error(`Health check returned ${response.status}`);
            }
            return;
        } catch (error) {
            lastError = error;
            await scheduler.wait(200);
        }
    }
    throw new Error(`Container did not become ready on port ${options.port}`, {
        cause: lastError,
    });
}

src/utils.tsts

interface ReadinessOptions {
    port: number;
    inactivityTimeout: number;
}

type ContainerInstance = NonNullable<DurableObjectState["container"]>;

export function rewriteRequestForContainer(request: Request): Request {
    const url = new URL(request.url);
    url.protocol = "http:";
    url.host = "container";
    const forwarded = new Request(url, request);
    forwarded.headers.delete("host");
    return forwarded;
}

export async function startAndWaitForPort(
    container: ContainerInstance,
    options: ReadinessOptions,
): Promise<void> {
    await container.setInactivityTimeout(options.inactivityTimeout);
    if (!container.running) {
        container.start();
    }

    // start() returns before the container is ready, so poll its health endpoint.
    const port = container.getTcpPort(options.port);
    let lastError: unknown;
    for (let attempt = 0; attempt < 100; attempt++) {
        try {
            const response = await port.fetch("http://container/health");
            if (!response.ok) {
                throw new Error(`Health check returned ${response.status}`);
            }
            return;
        } catch (error) {
            lastError = error;
            await scheduler.wait(200);
        }
    }
    throw new Error(`Container did not become ready on port ${options.port}`, {
        cause: lastError,
    });
}
{
    "name": "container-starter",
    "main": "src/index.ts",
    "upload_source_maps": true,
    // Set this to today's date
    "compatibility_date": "2026-10-27",
    "containers": [
        {
            "class_name": "MyContainer",
            "image": "./Dockerfile",
            "max_instances": 5,
        },
    ],
    "durable_objects": {
        "bindings": [
            {
                "class_name": "MyContainer",
                "name": "MY_CONTAINER",
            },
        ],
    },
    "exports": {
        "MyContainer": {
            "type": "durable-object",
            "storage": "sqlite",
        },
    },
}
name = "container-starter"
main = "src/index.ts"
upload_source_maps = true
# Set this to today's date
compatibility_date = "2026-10-27"

[[containers]]
class_name = "MyContainer"
image = "./Dockerfile"
max_instances = 5

[[durable_objects.bindings]]
class_name = "MyContainer"
name = "MY_CONTAINER"

[exports.MyContainer]
type = "durable-object"
storage = "sqlite"

Get started Containers dashboard


Next steps

Get started

Build and push an image, call a Container from a Worker, and try scaling and routing.

Deploy a Container

Examples

Stateless and stateful routing, regional placement, Workflow and Queue integrations, AI-generated code execution, and short-lived workloads.

See Examples

Local development

Run your Worker and container together with wrangler dev or vite dev before you deploy.

Develop locally

Deploy

Ship from your machine or Workers Builds, and confirm the deploy.

Deploy Containers


More resources

Scheduling policies

Choose whether image and instance configuration is managed centrally or from Durable Object code.

Rollouts

How container instances update after you deploy.

Image management

Build, push, and pull images for Containers.

Lifecycle of a Container

How a container is scheduled, started, routed, and shut down.

Limits

Instance counts, image size, and other platform limits.

Wrangler

CLI commands for images and containers.

APIs

Use the Durable Object Container API or reference the Container class.

SSH

Connect to running container instances with SSH through Wrangler.

Containers Discord

Ask questions, show what you are building, and talk with other Containers developers.

Was this helpful?

YesNo

On this page

Containers - 图1Docs

{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/containers/#page","headline":"Containers","description":"Run serverless containers alongside Workers to handle resource-intensive workloads, custom runtimes, and existing container images on Cloudflare.","url":"https://developers.cloudflare.com/containers/","inLanguage":"en","image":"https://developers.cloudflare.com/containers/og.png?v=9068707d88e89d36","dateModified":"2026-10-12","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}


description: Deploy your first Container on Cloudflare by building an image, configuring a Worker, and routing requests to container instances. title: Get started image: https://developers.cloudflare.com/containers/get-started/og.png?v=82557fc11168d06b


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/containers/llms.txt
Use this file to discover all available pages before exploring further.