From 4811ec668ba39ba58b4de0b426a77d0c848fcd3e Mon Sep 17 00:00:00 2001 From: Greg Anders Date: Thu, 26 Mar 2026 16:05:32 -0500 Subject: [PATCH 1/2] Add docs and changelog for containers snapshots --- .../containers/2026-09-03-snapshots.mdx | 56 +++++++++++++++ .../docs/containers/concepts/architecture.mdx | 11 +-- src/content/docs/containers/faq.mdx | 9 +-- .../docs/containers/guides/snapshots.mdx | 71 +++++++++++++++++++ .../docs/durable-objects/api/container.mdx | 30 ++++++++ 5 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 src/content/changelog/containers/2026-09-03-snapshots.mdx create mode 100644 src/content/docs/containers/guides/snapshots.mdx diff --git a/src/content/changelog/containers/2026-09-03-snapshots.mdx b/src/content/changelog/containers/2026-09-03-snapshots.mdx new file mode 100644 index 00000000000..ff8924d1388 --- /dev/null +++ b/src/content/changelog/containers/2026-09-03-snapshots.mdx @@ -0,0 +1,56 @@ +--- +title: Snapshot and restore Container state +description: Persist point-in-time container filesystem with experimental snapshot APIs. +products: + - containers +date: 2026-09-03 +--- + +import { TypeScriptExample } from "~/components"; + +[Containers](/containers/) now support experimental snapshot APIs for saving and restoring point-in-time filesystem state. Create a snapshot first, then pass it back to `start()` to restore files after container sleep, restart, or handoff to another Durable Object. + +Use `snapshotContainer()` to capture the full container filesystem. The example uses the [low-level Durable Object container API](/durable-objects/api/container/). Create snapshots from a container that is already running: + + + +```ts +import { DurableObject } from "cloudflare:workers"; + +export class MyDurableObject extends DurableObject { + async saveSnapshot() { + const containerSnapshot = await this.ctx.container.snapshotContainer({}); + + await this.ctx.storage.put("containerSnapshot", containerSnapshot); + } +} +``` + + + +Later, load the saved snapshot handle and restore it with `start()`: + + + +```ts +import { DurableObject } from "cloudflare:workers"; + +export class MyDurableObject extends DurableObject { + async restoreSnapshot() { + const containerSnapshot = + await this.ctx.storage.get("containerSnapshot"); + + if (!containerSnapshot) { + return; + } + + this.ctx.container.start({ containerSnapshot }); + } +} +``` + + + +Snapshots are immutable. + +For more information, refer to [Snapshots](/containers/guides/snapshots/) and [Durable Object Container](/durable-objects/api/container/). diff --git a/src/content/docs/containers/concepts/architecture.mdx b/src/content/docs/containers/concepts/architecture.mdx index 4b3c7b4da8a..e16430b8525 100644 --- a/src/content/docs/containers/concepts/architecture.mdx +++ b/src/content/docs/containers/concepts/architecture.mdx @@ -114,13 +114,14 @@ The [`Container` class](/containers/reference/container-class/) provides hooks t Refer to the [status hooks example](/containers/examples/status-hooks/) for a full implementation. -#### Persistent disk +#### Use snapshots -All disk is ephemeral. When a Container instance goes to sleep, the next time -it is started, it will have a fresh disk as defined by its container image. +All disk is ephemeral by default. When a Container instance goes to sleep, the +next time it starts, it uses a fresh disk from the container image. -Snapshots are coming soon, which allow the user to quickly persist and restore the disk -from an entire container or a directory. +If you need point-in-time filesystem state, create and restore a snapshot. +Snapshots are immutable, so later file changes require a new snapshot. For more +information, refer to [Snapshots](/containers/guides/snapshots/). You can also use [FUSE](/containers/examples/r2-fuse-mount/) to persist disk to R2 or other object storage backends. Though you should not expect native diff --git a/src/content/docs/containers/faq.mdx b/src/content/docs/containers/faq.mdx index 77b127711ec..c8a12ecbfa3 100644 --- a/src/content/docs/containers/faq.mdx +++ b/src/content/docs/containers/faq.mdx @@ -104,11 +104,12 @@ Refer to [image management](/containers/guides/image-management/#use-pre-built-c ## Is disk persistent? What happens to my disk when my container sleeps? -All disk is ephemeral. When a Container instance goes to sleep, the next time -it is started, it will have a fresh disk as defined by its container image. +All disk is ephemeral by default. When a Container instance goes to sleep, the +next time it starts, it uses a fresh disk from the container image. -Snapshots are coming soon, which allow the user to quickly persist and restore the disk -from an entire container or a directory. +If you need point-in-time filesystem state, create and restore a snapshot. +Snapshots are immutable, so later file changes require a new snapshot. For more +information, refer to [Snapshots](/containers/guides/snapshots/). You can also use [FUSE](/containers/examples/r2-fuse-mount/) to persist disk to R2 or other object storage backends. Though you should not expect native diff --git a/src/content/docs/containers/guides/snapshots.mdx b/src/content/docs/containers/guides/snapshots.mdx new file mode 100644 index 00000000000..2a2f8ca8037 --- /dev/null +++ b/src/content/docs/containers/guides/snapshots.mdx @@ -0,0 +1,71 @@ +--- +title: Use snapshots +pcx_content_type: how-to +sidebar: + order: 7 +description: Persist container filesystem across restarts. +--- + +import { TypeScriptExample } from "~/components"; + +Snapshots let you save point-in-time filesystem state from a running [Container](/containers/). The examples on this page use the [low-level Durable Object container API](/durable-objects/api/container/). + +## Create a container snapshot + +Use `snapshotContainer()` to capture the full container filesystem. Snapshots are immutable. If you restore a snapshot and then change files, create a new snapshot to persist those changes. + +The returned snapshot handle is a plain data object. You can store it and restore it later, including from another Durable Object: + + + +```ts +import { DurableObject } from "cloudflare:workers"; + +export class MyDurableObject extends DurableObject { + async saveContainer() { + const containerSnapshot = await this.ctx.container.snapshotContainer({ + name: "before-upgrade", + }); + + await this.ctx.storage.put("containerSnapshot", containerSnapshot); + } +} +``` + + + +## Restore a container snapshot + +Load the saved snapshot handle. Then, pass it to `this.ctx.container.start()` when you start another container: + + + +```ts +import { DurableObject } from "cloudflare:workers"; + +export class MyDurableObject extends DurableObject { + async restoreContainer() { + const containerSnapshot = + await this.ctx.storage.get("containerSnapshot"); + + if (!containerSnapshot) { + return; + } + + this.ctx.container.start({ containerSnapshot }); + } +} +``` + + + +## Understand retention + +Snapshots currently have an implicit 30-day time-to-live. Each restore refreshes that time-to-live. + +You cannot set a custom time-to-live yet. + +## Related resources + +- [Durable Object Container](/durable-objects/api/container/) - Full `ctx.container` API reference +- [Lifecycle of a Container](/containers/concepts/architecture/) - Understand startup, sleep, and shutdown behavior diff --git a/src/content/docs/durable-objects/api/container.mdx b/src/content/docs/durable-objects/api/container.mdx index e335a576411..42f19160932 100644 --- a/src/content/docs/durable-objects/api/container.mdx +++ b/src/content/docs/durable-objects/api/container.mdx @@ -77,6 +77,7 @@ this.ctx.container.start({ - `env`: An object containing environment variables to pass to the container. This is useful for passing configuration values or secrets to the container. - `entrypoint`: An array of strings representing the command to run in the container. - `enableInternet`: A boolean indicating whether to enable internet access for the container. + - `containerSnapshot`: A full container snapshot to restore before the container starts. #### Return values @@ -163,6 +164,34 @@ With `stderr: "combined"`, `stderr` is `null` on `ExecProcess` and an empty `Arr For task-oriented examples, refer to [Execute commands](/containers/guides/execute-commands/). +### `snapshotContainer` + +`snapshotContainer` creates a point-in-time snapshot of the full running container filesystem. + + + +```ts +const snapshot = await this.ctx.container.snapshotContainer({ + name: "before-upgrade", +}); +``` + + + +#### Parameters + +- `options`: An object with the following properties: + - `name` (optional string): A human-friendly name for the snapshot. + +#### Return values + +- A promise that resolves to a `ContainerSnapshot` object with `id`, `size`, and optional `name` properties. + +#### Notes + +- Container snapshots are immutable. +- Snapshot handles currently have an implicit 30-day time-to-live that refreshes when you restore them. + ### `destroy` `destroy` stops the container and optionally returns a custom error message to the `monitor()` error callback. @@ -343,3 +372,4 @@ this.ctx.container.interceptOutboundHttps("*", worker); - [Get started with Containers](/containers/get-started/) - [SQLite storage API](/durable-objects/api/sqlite-storage-api/) — persist state across container restarts - [Durable Objects](/durable-objects/) — the underlying platform that powers Containers +- [Snapshots](/containers/guides/snapshots/) \ No newline at end of file From a730273d0dce21de27dc77e799cef5799095e282 Mon Sep 17 00:00:00 2001 From: Thomas Gauvin Date: Fri, 18 Sep 2026 11:46:57 -0400 Subject: [PATCH 2/2] [Containers] Document Durable Object scheduling policy --- ...09-28-durable-object-scheduling-policy.mdx | 50 +++++ .../docs/containers/concepts/architecture.mdx | 21 +-- .../configuration/environment-variables.mdx | 2 +- .../docs/containers/configuration/index.mdx | 2 +- .../containers/configuration/rollouts.mdx | 6 +- .../configuration/scaling-and-routing.mdx | 2 +- .../configuration/scheduling-policy.mdx | 171 ++++++++++++++++++ .../configuration/workers-connections.mdx | 2 +- .../containers/guides/image-management.mdx | 4 + src/content/docs/containers/index.mdx | 8 + .../docs/containers/platform/limits.mdx | 6 +- .../docs/durable-objects/api/container.mdx | 50 +++-- .../docs/workers/wrangler/configuration.mdx | 58 +++++- 13 files changed, 342 insertions(+), 40 deletions(-) create mode 100644 src/content/changelog/containers/2026-09-28-durable-object-scheduling-policy.mdx create mode 100644 src/content/docs/containers/configuration/scheduling-policy.mdx diff --git a/src/content/changelog/containers/2026-09-28-durable-object-scheduling-policy.mdx b/src/content/changelog/containers/2026-09-28-durable-object-scheduling-policy.mdx new file mode 100644 index 00000000000..dae009399cd --- /dev/null +++ b/src/content/changelog/containers/2026-09-28-durable-object-scheduling-policy.mdx @@ -0,0 +1,50 @@ +--- +title: Configure Container image and instance size at runtime +description: The durable_object scheduling policy gives each Durable Object control of Container configuration. +products: + - containers +date: 2026-09-28 +--- + +import { TypeScriptExample, WranglerConfig } from "~/components"; + +[Containers](/containers/) now support the `durable_object` scheduling policy in public beta. This policy lets a Durable Object select the image and instance size for a Container at runtime instead of using one centrally managed configuration for the application. + +Configure the policy and one or more named images in Wrangler: + + + +```jsonc +{ + "containers": [ + { + "class_name": "AgentComputer", + "scheduling_policy": "durable_object", + "images": { + "base": { + "dockerfile": "./container/Dockerfile", + }, + }, + }, + ], +} +``` + + + +Wrangler prepares each image and exposes its immutable reference through `ctx.container.images`. Supply that reference and an instance size when you start the Container: + + + +```ts +this.ctx.container.start({ + image: this.ctx.container.images.base, + instance: "standard-2", +}); +``` + + + +Durable Object-managed Container instances have independent lifecycles and do not participate in application-wide image rollouts. The existing `default` policy and its rollout behavior are unchanged. + +For configuration, runtime sizing, snapshots, and update behavior, refer to [Scheduling Policies](/containers/configuration/scheduling-policy/). diff --git a/src/content/docs/containers/concepts/architecture.mdx b/src/content/docs/containers/concepts/architecture.mdx index e16430b8525..e7c189c26c7 100644 --- a/src/content/docs/containers/concepts/architecture.mdx +++ b/src/content/docs/containers/concepts/architecture.mdx @@ -10,12 +10,13 @@ products: ## Deployment -After you deploy an application with a Container, your image is uploaded to -[Cloudflare's Registry](/containers/guides/image-management/) and distributed globally to Cloudflare's Network. -Cloudflare will pre-schedule instances and pre-fetch images across the globe to ensure quick start -times when scaling up the number of concurrent container instances. +How images and running Container instances update depends on the [scheduling policy](/containers/configuration/scheduling-policy/) for the application. -Worker code goes live on deploy. Container instances update with a [rollout](/containers/configuration/rollouts/). Refer to [Deploy Containers](/containers/guides/deploy/). +With the `default` policy, Wrangler uploads or resolves the application image. Cloudflare distributes that image across its network and prepares capacity for new instances. Changes to the image or instance type use a [rollout](/containers/configuration/rollouts/). + +With the `durable_object` policy, Wrangler prepares the named images for the application. Durable Object code can access their immutable references. The code selects an image and instance size when it calls `ctx.container.start()`. Running instances do not participate in application-wide image rollouts. + +Worker code goes live on deploy before any application-wide Container rollout finishes. Refer to [Deploy Containers](/containers/guides/deploy/). ## Lifecycle of a Request @@ -41,8 +42,7 @@ state associated with each instance. ### Starting a Container -When a Durable Object instance requests to start a new container instance, the **nearest location -with a pre-fetched image** is selected. +When a Durable Object requests a new Container instance, Cloudflare selects eligible capacity with the required image available. The `default` policy uses the application image and instance type from Wrangler configuration. The `durable_object` policy uses the `image` and `instance` options supplied to `ctx.container.start()`. :::note Durable Objects and their associated Container instances are not guaranteed to run in the @@ -52,12 +52,7 @@ Container placement is optimized for request routing and startup speed, so a Con start in a different location than its Durable Object. ::: -Starting additional container instances will use other locations with pre-fetched images, -and Cloudflare will automatically begin prepping additional machines behind the scenes -for additional scaling and quick cold starts. Because there are a finite number of pre-warmed -locations, some container instances may be started in locations that are farther away from -the end-user. This is done to ensure that the container instance starts quickly. You are -only charged for actively running instances and not for any unused pre-warmed images. +Starting additional Container instances can use other locations where the image is available. Cloudflare prepares additional capacity as demand grows. Because prepared capacity is finite, some Container instances may start in locations farther from the end user. You are only charged for actively running instances, not for prepared images that are not running. #### Cold starts diff --git a/src/content/docs/containers/configuration/environment-variables.mdx b/src/content/docs/containers/configuration/environment-variables.mdx index 62612167fa4..ac71f31fa1c 100644 --- a/src/content/docs/containers/configuration/environment-variables.mdx +++ b/src/content/docs/containers/configuration/environment-variables.mdx @@ -3,7 +3,7 @@ pcx_content_type: reference title: Environment Variables description: Runtime and user-defined environment variables available inside Container instances. sidebar: - order: 2 + order: 3 products: - containers --- diff --git a/src/content/docs/containers/configuration/index.mdx b/src/content/docs/containers/configuration/index.mdx index a49102d100a..4b06ca82c16 100644 --- a/src/content/docs/containers/configuration/index.mdx +++ b/src/content/docs/containers/configuration/index.mdx @@ -1,7 +1,7 @@ --- pcx_content_type: navigation title: Configuration -description: Configure Containers — connect them to Workers and bindings, set environment variables, tune scaling and routing, and manage rollouts. +description: Choose a scheduling policy, connect Containers to Workers and bindings, set environment variables, tune scaling and routing, and manage rollouts. sidebar: order: 5 group: diff --git a/src/content/docs/containers/configuration/rollouts.mdx b/src/content/docs/containers/configuration/rollouts.mdx index d658eb17a03..f66457e81a9 100644 --- a/src/content/docs/containers/configuration/rollouts.mdx +++ b/src/content/docs/containers/configuration/rollouts.mdx @@ -3,13 +3,17 @@ pcx_content_type: reference title: Rollouts description: How container instances update after a deploy, including step percentages, grace periods, and rollout modes. sidebar: - order: 4 + order: 5 products: - containers --- import { WranglerConfig, PackageManagers } from "~/components"; +:::note +Rollouts apply to Container applications that use the [`default` scheduling policy](/containers/configuration/scheduling-policy/). Durable Object-managed Container instances do not participate in application-wide rollouts; application code selects their image when it calls `ctx.container.start()`. +::: + ## How rollouts work A **rollout** applies a target container application configuration after you [deploy](/containers/guides/deploy/) a Worker that uses Containers. The target can change the image, instance type, limits, placement, or other container settings. diff --git a/src/content/docs/containers/configuration/scaling-and-routing.mdx b/src/content/docs/containers/configuration/scaling-and-routing.mdx index 7306d9c20c9..877ca0f005d 100644 --- a/src/content/docs/containers/configuration/scaling-and-routing.mdx +++ b/src/content/docs/containers/configuration/scaling-and-routing.mdx @@ -3,7 +3,7 @@ pcx_content_type: reference title: Scaling and Routing description: Scale Container instances using explicit IDs or the getRandom helper for stateless load balancing. sidebar: - order: 3 + order: 4 products: - containers --- diff --git a/src/content/docs/containers/configuration/scheduling-policy.mdx b/src/content/docs/containers/configuration/scheduling-policy.mdx new file mode 100644 index 00000000000..db3913c70be --- /dev/null +++ b/src/content/docs/containers/configuration/scheduling-policy.mdx @@ -0,0 +1,171 @@ +--- +pcx_content_type: concept +title: Scheduling Policies +description: Choose whether Container configuration is managed centrally or by each Durable Object at runtime. +sidebar: + order: 1 +products: + - containers +--- + +import { TypeScriptExample, WranglerConfig } from "~/components"; + +A scheduling policy determines where you configure a Container image and instance size. It also determines how image updates apply. Choose the policy when you create the Container application. + +| Policy | Configure image and instance size | Image updates | Best for | +| - | - | - | - | +| `default` | In Wrangler configuration | Cloudflare applies application-wide configuration changes with [rollouts](/containers/configuration/rollouts/) | Services whose instances use the same image and instance size | +| `durable_object` | In Durable Object code when calling `ctx.container.start()` | Application code selects an image each time it starts an instance | Sandboxes, agent environments, and other workloads that need per-instance configuration | + +The scheduling policy is immutable. To use a different policy, create a new Container application. Deleting and recreating an application also replaces its Container instances. + +:::note +The `durable_object` scheduling policy is in public beta. +::: + +## Use the default scheduling policy + +The `default` policy preserves the existing Containers behavior. Define one `image`, one `instance_type`, and application-level settings such as `max_instances` in Wrangler configuration. Omitting `scheduling_policy` selects `default`. + + + +```jsonc +{ + "containers": [ + { + "class_name": "ApiContainer", + "scheduling_policy": "default", + "image": "./api/Dockerfile", + "instance_type": "standard-1", + "max_instances": 5, + }, + ], +} +``` + + + +When you change the image or instance type and deploy, Cloudflare rolls out that change across the application. Refer to [Rollouts](/containers/configuration/rollouts/). + +## Use the Durable Object scheduling policy + +The `durable_object` policy moves per-instance decisions into your Durable Object. Wrangler associates the Container application with the Durable Object class, and your code supplies a startup image or snapshot and an optional instance size to `ctx.container.start()`. + +Configure the policy and the images that the Durable Object can start: + + + +```jsonc +{ + "name": "agent-computer", + "main": "src/index.ts", + "compatibility_date": "$today", + "containers": [ + { + "class_name": "AgentComputer", + "scheduling_policy": "durable_object", + "images": { + "base": { + "dockerfile": "./container/Dockerfile", + }, + }, + }, + ], + "durable_objects": { + "bindings": [ + { + "name": "AGENT_COMPUTER", + "class_name": "AgentComputer", + }, + ], + }, + "migrations": [ + { + "tag": "v1", + "new_sqlite_classes": ["AgentComputer"], + }, + ], +} +``` + + + +Wrangler builds or resolves each named image, prepares it for the Containers runtime, and exposes its digest-pinned reference on `ctx.container.images`. Select an image and instance size when the Durable Object starts its Container: + + + +```ts +import { DurableObject } from "cloudflare:workers"; + +export class AgentComputer extends DurableObject { + startContainer() { + if (this.ctx.container.running) { + return; + } + + this.ctx.container.start({ + image: this.ctx.container.images.base, + instance: "standard-2", + enableInternet: true, + }); + } +} +``` + + + +`ctx.container.start()` initiates startup and returns before the Container is ready to accept requests. Add an application-specific readiness check before sending traffic or calling [`exec()`](/durable-objects/api/container/#exec). + +### Configure named images + +Each key in `images` is a name you choose. Each value must specify exactly one image source. Use `dockerfile` for a path to a Dockerfile. Wrangler builds and uploads the image. You can also set `build_context` and `build_vars` for that image. + +Use `image` for a digest-pinned image in the Cloudflare managed registry. Use the form `registry.cloudflare.com//@sha256:`. + +A configuration can contain up to 100 named images. An image name must contain between 1 and 128 characters. + +The image map is uploaded with the Worker version. Updating the map does not restart or replace running Container instances. Your application selects an image from the map when it starts an instance. + +### Choose an instance size at runtime + +Set `instance` in `ctx.container.start()` to one of the following named instance types: + +- `lite` +- `standard-1` +- `standard-2` +- `standard-3` +- `standard-4` + +If you omit `instance`, the Container uses `lite`. You can also supply a custom instance object: + +```ts +this.ctx.container.start({ + image: this.ctx.container.images.base, + instance: { + vcpu: 1, + memoryMib: 4096, + diskMb: 8000, + }, +}); +``` + +The runtime uses camel case (`memoryMib` and `diskMb`). Wrangler's application-level `instance_type` object uses snake case (`memory_mib` and `disk_mb`) and only applies to the `default` policy. Refer to [Limits and Instance Types](/containers/platform/limits/). + +### Start from an image or snapshot + +For a new filesystem, pass `image` to `ctx.container.start()`. To restore a full filesystem snapshot, pass `containerSnapshot` instead. `image` and `containerSnapshot` are mutually exclusive because a snapshot already identifies the filesystem to restore. + +Refer to [Snapshots](/containers/guides/snapshots/) for the complete save and restore flow. + +### Manage updates from application code + +Container instances that use the `durable_object` policy do not participate in application-wide image rollouts. A running instance continues to use its startup image. Your application decides when to stop that instance and start it with another configured image. + +One Wrangler configuration can contain applications with both policies. This lets a Worker use centrally managed service Containers alongside Durable Object-managed sandboxes. + +## Related resources + +- [Durable Object Container API](/durable-objects/api/container/) +- [Lifecycle of a Container](/containers/concepts/architecture/) +- [Image Management](/containers/guides/image-management/) +- [Wrangler Containers configuration](/workers/wrangler/configuration/#containers) diff --git a/src/content/docs/containers/configuration/workers-connections.mdx b/src/content/docs/containers/configuration/workers-connections.mdx index bd00691c72f..16145faa7ac 100644 --- a/src/content/docs/containers/configuration/workers-connections.mdx +++ b/src/content/docs/containers/configuration/workers-connections.mdx @@ -2,7 +2,7 @@ title: Connect to Workers and Bindings pcx_content_type: concept sidebar: - order: 1 + order: 2 description: Access KV, R2, Durable Objects, and other bindings from a container. products: - containers diff --git a/src/content/docs/containers/guides/image-management.mdx b/src/content/docs/containers/guides/image-management.mdx index dff2c55fdca..edd0e235459 100644 --- a/src/content/docs/containers/guides/image-management.mdx +++ b/src/content/docs/containers/guides/image-management.mdx @@ -10,6 +10,10 @@ products: import { WranglerConfig, PackageManagers, Steps } from "~/components"; +:::note +The `image` examples on this page apply to Container applications that use the [`default` scheduling policy](/containers/configuration/scheduling-policy/). For the `durable_object` policy, configure a named `images` map and select an image from `ctx.container.images` at runtime. A named `image` entry must be a digest-pinned reference in the Cloudflare managed registry; a named `dockerfile` entry can build from an external base image. +::: + ## Push images during `wrangler deploy` When running `wrangler deploy`, if you set the `image` attribute in your [Wrangler configuration](/workers/wrangler/configuration/#containers) to a path to a Dockerfile, Wrangler will build your container image locally using Docker, then push it to a registry run by Cloudflare. diff --git a/src/content/docs/containers/index.mdx b/src/content/docs/containers/index.mdx index a2cf34aff99..0b6f62aa042 100644 --- a/src/content/docs/containers/index.mdx +++ b/src/content/docs/containers/index.mdx @@ -146,6 +146,14 @@ Ship from your machine or Workers Builds, and confirm the deploy. + + Choose whether image and instance configuration is managed centrally or from Durable Object code. + + -These are specified using the [`instance_type` property](/workers/wrangler/configuration/#containers) in your Worker's Wrangler configuration file. +For an application that uses the [`default` scheduling policy](/containers/configuration/scheduling-policy/), specify the size with the [`instance_type` property](/workers/wrangler/configuration/#containers) in your Worker's Wrangler configuration file. For the `durable_object` policy, pass the named size to `ctx.container.start()` with the runtime `instance` property. :::note The `dev` and `standard` instance types are preserved for backward compatibility and are aliases for `lite` and `standard-1`, respectively. @@ -24,7 +24,9 @@ The `dev` and `standard` instance types are preserved for backward compatibility ### Custom Instance Types -In addition to the predefined instance types, you can configure custom instance types by specifying `vcpu`, `memory_mib`, and `disk_mb` values. See the [Wrangler configuration documentation](/workers/wrangler/configuration/#custom-instance-types) for configuration details. +In addition to the predefined instance types, you can configure custom instance types. Field names depend on where you configure the size. Wrangler configuration for the `default` policy uses `vcpu`, `memory_mib`, and `disk_mb`. A `ctx.container.start()` call for the `durable_object` policy uses `vcpu`, `memoryMib`, and `diskMb`. + +Refer to the [Wrangler configuration documentation](/workers/wrangler/configuration/#custom-instance-types) or [scheduling policy documentation](/containers/configuration/scheduling-policy/#choose-an-instance-size-at-runtime) for examples. Custom instance types have the following constraints: diff --git a/src/content/docs/durable-objects/api/container.mdx b/src/content/docs/durable-objects/api/container.mdx index 42f19160932..e0826335476 100644 --- a/src/content/docs/durable-objects/api/container.mdx +++ b/src/content/docs/durable-objects/api/container.mdx @@ -26,43 +26,57 @@ The low-level API documented on this page is available on `this.ctx.container` i Because the `Container` class extends `DurableObject`, you also have access to [SQLite storage](/durable-objects/api/sqlite-storage-api/) via `this.ctx.storage`, [alarms](/durable-objects/api/alarms/), and all other Durable Object APIs. +The following example uses the image configured by an application with the [`default` scheduling policy](/containers/configuration/scheduling-policy/#use-the-default-scheduling-policy): + + ```ts +import { DurableObject } from "cloudflare:workers"; + export class MyDurableObject extends DurableObject { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); - // boot the container when starting the DO - this.ctx.blockConcurrencyWhile(async () => { - this.ctx.container.start(); - }); - } - + // Start the container when this Durable Object is activated. + this.ctx.blockConcurrencyWhile(async () => { + this.ctx.container.start(); + }); + } } +``` -```` - ## Attributes +### `images` + +`images` is a read-only map of the named images configured for a Container application that uses the [`durable_object` scheduling policy](/containers/configuration/scheduling-policy/#use-the-durable-object-scheduling-policy). Each value is a digest-pinned image reference prepared by Wrangler. + +```ts +this.ctx.container.images.base; +``` + +Pass a value from this map as the `image` option to [`start()`](#start). + ### `running` -`running` returns `true` if the container is currently running. It does not ensure that the container has fully started and ready to accept requests. +`running` returns `true` if the container is currently running. It does not ensure that the container has fully started and is ready to accept requests. ```js - this.ctx.container.running; -```` +this.ctx.container.running; +``` ## Methods ### `start` -`start` boots a container. This method does not block until the container is fully started. -You may want to confirm the container is ready to accept requests before using it. +`start` boots a container. This method returns before the container is fully started. Confirm that the container is ready to accept requests before using it. -```js +```ts this.ctx.container.start({ + image: this.ctx.container.images.base, + instance: "standard-2", env: { FOO: "bar", }, @@ -77,11 +91,13 @@ this.ctx.container.start({ - `env`: An object containing environment variables to pass to the container. This is useful for passing configuration values or secrets to the container. - `entrypoint`: An array of strings representing the command to run in the container. - `enableInternet`: A boolean indicating whether to enable internet access for the container. - - `containerSnapshot`: A full container snapshot to restore before the container starts. + - `image`: The image reference to start. For a Container application that uses the `durable_object` scheduling policy, pass a reference from [`ctx.container.images`](#images) unless you are restoring a snapshot. + - `instance`: The instance size to use for a Container application that uses the `durable_object` scheduling policy. Pass `"lite"`, `"standard-1"`, `"standard-2"`, `"standard-3"`, `"standard-4"`, or a custom object with `vcpu`, `memoryMib`, and `diskMb` properties. Defaults to `"lite"`. + - `containerSnapshot`: A full container snapshot to restore before the container starts. You cannot use `containerSnapshot` and `image` in the same call. #### Return values -- None. +- None. Startup continues asynchronously. ### `exec` @@ -372,4 +388,4 @@ this.ctx.container.interceptOutboundHttps("*", worker); - [Get started with Containers](/containers/get-started/) - [SQLite storage API](/durable-objects/api/sqlite-storage-api/) — persist state across container restarts - [Durable Objects](/durable-objects/) — the underlying platform that powers Containers -- [Snapshots](/containers/guides/snapshots/) \ No newline at end of file +- [Snapshots](/containers/guides/snapshots/) diff --git a/src/content/docs/workers/wrangler/configuration.mdx b/src/content/docs/workers/wrangler/configuration.mdx index d00bb62f126..78ccd777cdf 100644 --- a/src/content/docs/workers/wrangler/configuration.mdx +++ b/src/content/docs/workers/wrangler/configuration.mdx @@ -1259,6 +1259,8 @@ You can also configure `run_worker_first` with an array of route patterns: You can define [Containers](/containers) to run alongside your Worker using the `containers` field. +Each Container application has a [scheduling policy](/containers/configuration/scheduling-policy/) that determines whether image and instance configuration is managed centrally or supplied by Durable Object code at runtime. The policy is immutable after the application is created. + :::note You must also define a Durable Object to communicate with your Container via Workers. This Durable Object's class name must match the `class_name` value in container configuration. @@ -1266,19 +1268,26 @@ class name must match the `class_name` value in container configuration. The following options are available: -- `image` +- `scheduling_policy` + - `"default"` uses the centrally configured application image, instance type, limits, and rollouts. This is the default when the field is omitted. + - `"durable_object"` lets each Durable Object supply its Container image and instance size to `ctx.container.start()`. Refer to [Scheduling Policies](/containers/configuration/scheduling-policy/). +- `image` - The image to use for the container. This can either be a local path to a `Dockerfile`, in which case `wrangler deploy` will build and push the image, or it can be an image reference. Supported registries are the Cloudflare Registry, Docker Hub, Amazon ECR, and Google Artifact Registry. For more information, refer to [Image Management](/containers/guides/image-management/). +- `images` + - Named images that Durable Object code can access through `ctx.container.images`. A configuration can contain up to 100 named images, and each name must contain 1-128 characters. + - Each named image must set exactly one of `dockerfile` or `image`. `dockerfile` is a local Dockerfile path and can also set `build_context` and `build_vars`. `image` must be a digest-pinned reference in the Cloudflare managed registry. - `class_name` - The corresponding Durable Object class name. This will make this Durable Object a container-enabled Durable Object and allow each instance to control a container. See [Durable Object Container Methods](/durable-objects/api/container/) for details. - `instance_type` - - The instance type of the container. This determines the amount of memory, CPU, and disk given to the container + - The instance type for the `default` policy. This determines the amount of memory, CPU, and disk given to the container instance. The current options are `"lite"`, `"basic"`, `"standard-1"`, `"standard-2"`, `"standard-3"`, and `"standard-4"`. The default is `"lite"`. For more information, see the [instance types documentation](/containers/platform/limits/#instance-types). + - For the `durable_object` policy, set the runtime `instance` option in `ctx.container.start()` instead. - To specify a custom instance type, see [here](#custom-instance-types). - `max_instances` - - The maximum number of concurrent container instances you want to run at any given moment. Stopped containers do not count towards this - you may have more container instances than this number overall, but only this many actively running containers at once. If a request to start a container will exceed this limit, that request will error. + - The maximum number of concurrent container instances for the `default` policy. Stopped containers do not count towards this - you may have more container instances than this number overall, but only this many actively running containers at once. If a request to start a container will exceed this limit, that request will error. - Defaults to 20. - This value is only enforced when running in production on Cloudflare's network. This limit does not apply during local development, so you may run more instances than specified. - `name` @@ -1312,6 +1321,7 @@ The following options are available: "containers": [ { "class_name": "MyContainer", + "scheduling_policy": "default", "image": "./Dockerfile", "max_instances": 10, "instance_type": "basic", // Optional, defaults to "lite" @@ -1343,6 +1353,48 @@ The following options are available: +For the `durable_object` policy, name one or more images and select one from Durable Object code when the Container starts: + + + +```jsonc +{ + "containers": [ + { + "class_name": "AgentComputer", + "scheduling_policy": "durable_object", + "images": { + "base": { + "dockerfile": "./container/Dockerfile", + "build_context": ".", + "build_vars": { + "APP_ENV": "production", + }, + }, + }, + }, + ], + "durable_objects": { + "bindings": [ + { + "name": "AGENT_COMPUTER", + "class_name": "AgentComputer", + }, + ], + }, + "migrations": [ + { + "tag": "v1", + "new_sqlite_classes": ["AgentComputer"], + }, + ], +} +``` + + + +Only policy-level fields such as `name`, `class_name`, `scheduling_policy`, and `images` apply to a Durable Object-managed entry. Configure its image and instance size in `ctx.container.start()` instead of setting `image`, `instance_type`, or rollout fields here. + ### Custom Instance Types In place of the [named instance types](/containers/platform/limits/#instance-types), you can set a custom instance type by individually configuring vCPU, memory, and disk.