跳到正文
cloudflare blog· Thomas Gauvin·· 16 小時前精選AI 評分73

Cloudflare Containers 重構以擴充套件代理沙箱

Cloudflare Containers, rebuilt to scale agent sandboxes

AI 導讀

Cloudflare Containers 通過可程式設計排程、執行時映象選擇和檔案快照功能,啟動速度提升 6 倍,支援按需建立沙箱並即時恢復。

ComputeSDK 基準測試顯示,容器啟動時間從 4.049 秒降至 648 毫秒,且在 5 萬個容器的突發測試中,單賬號 100,000 個容器在 5.387 秒內完成啟動。

推薦理由

Cloudflare Containers 通過可程式設計排程和檔案快照,顯著提升代理沙箱啟動速度,幫助開發者更高效地構建和管理 AI 工作流。

正文 · AI 翻譯

今天,我們正在讓 Cloudflare Containers 更加可程式設計,並針對代理工作負載進行最佳化。代理不會提前部署沙箱。它們按需為每個任務建立沙箱,期望它們立即準備好,並能夠暫停和恢復。因此,我們重新架構了 Containers 以滿足這些需求:您的程式碼現在可以在執行時選擇每個沙箱的映象和例項型別,Containers 啟動速度提升 6 倍,檔案系統快照已在公開測試版中提供。

為實現這一點,我們從底層重新思考了 Containers 基礎設施。新的排程策略將對每個沙箱的控制權移交給應用程式碼,而重新設計的執行時則提供了更快的路徑來執行 Container。在 ComputeSDK 的獨立基準測試中,啟動時間中位數從略超過四秒降至 648 毫秒,在我們自己的初步測試中,突發測試成功在幾秒鐘內建立了數十萬個容器。

所有這些都建立在 Cloudflare Containers 一直以來的差異化基礎上:每個 Container 都擁有自己的 Durable Object,一個持久化、可程式設計的控制器,直接執行在其旁邊,管理生命週期、出站流量等。我們正在將更多功能直接帶到原生 ctx.container API,使 Durable Object 能夠在沒有包裝類的情況下控制其 Container,並且我們將此模型延伸到 Sandbox SDK 1.0。

正如我們今年早些時候所寫,你的代理需要一臺電腦。 這些更改使 Containers 在代理需要完整 Linux 工作空間時,成為 Workers、Dynamic Workers 和 Durable Objects 的更好補充。

為代理重新思考 Containers 的執行時

到目前為止,Cloudflare Containers 的組織方式圍繞應用部署。你在部署時選擇映象和計算資源,將該配置推廣到整個應用,並集中管理。應用是配置和釋出的單元。

代理工作空間不同:它是在代理工作時按需建立的。任務決定其映象、資源、工具和起始檔案系統。它可能只存在幾分鐘,在請求之間休眠,或在幾天後恢復。 這些決策需要與處理任務的應用程式碼一起存在,代理的沙箱需要快速啟動,因為每秒的啟動時間都是使用者等待的時間。

我們在 Base44 的應用構建工作空間和 Kilo Code 的雲代理會話中都看到過這種模式。它也出現在我們與 Cursor Cloud Agents、Devin Outposts、OpenAI Agents API 和 Claude Managed Agents 的整合中。

這些工作負載中的每一個都需要與工作空間不同的東西。編碼代理需要倉庫、包管理器、編譯器、測試執行器和開發伺服器。評估需要從已知狀態開始的沙箱。強化學習系統需要建立、評估和重置大量環境。長時間執行的任務需要保留代理生成的檔案,以便後續繼續工作。

這些需求促使我們從根本上重新思考了 Cloudflare Containers 的配置、排程和儲存方式。其成果是一種配置和排程容器的新方式:durable_object 排程策略。它讓你的程式碼能夠在執行時選擇每個沙盒的映象和計算資源,使容器啟動速度提升 6 倍以上,並支援檔案系統快照,從而能夠儲存和恢復工作區。

“在 Base44,我們幫助任何人將想法轉化為可用的應用程式。Cloudflare Containers 為每個應用程式提供了一個隔離的開發環境,我們的 AI 可以在其中執行命令、安裝依賴項,並在即時預覽中將更改變為現實。”
Dolev Epshtein,Base44 應用程式基礎設施軟體工程師
“在 Kilo Code,每個雲代理會話都需要自己的工作區和環境,並配有合適的程式碼庫、工具和使用者配置。Cloudflare Containers 讓我們能夠按需建立這些隔離的環境,以便我們的代理能夠快速開始執行命令併為客戶工作。”
Emilie Schario,Kilo Code 聯合創始人兼 Anaconda AI 工作區工程副總裁

為你的代理選擇所需的沙盒,從程式碼開始

從一開始,每個 Cloudflare Container 例項都附加到一個 Durable Object。Durable Object 為環境賦予了穩定的身份,並讓應用程式程式碼能夠控制其啟動、休眠和停止的時間。事實證明,這種模型特別適合代理沙盒。

然而,到目前為止,對代理沙盒最核心的兩個決定在部署時就已經鎖定了:它執行哪個映象以及獲得多少計算資源。映象和例項型別的每個組合都是其自己的 Containers 應用程式,擁有自己的 Durable Object 名稱空間,並需要提前通過 wrangler deploy 進行設定。 

假設一個代理需要一個小的 Node.js 沙盒,而另一個代理需要一個用於構建的大型 Python 沙盒。在我們的舊方法中,這需要兩個應用程式、兩個名稱空間,以及 Worker 中的路由邏輯,以便將每個任務傳送到正確的應用程式。每一個新環境都意味著另一次部署。 

新的 durable_object 排程策略消除了這一限制。映象和例項型別現在成了你的程式碼在沙盒啟動時傳遞的引數。要啟用此功能,請設定排程策略並宣告你的 Durable Object 可以選擇的映象:

你宣告的每個映象在 Durable Object 中都可以作為 this.ctx.container.images.<name> 使用。當任務到達時,你的程式碼會為該任務挑選映象和例項型別:

這段程式碼在任務已知後做出兩個決定。它選擇工作區需要的工具鏈以及為其分配多少計算資源。過去需要單獨的應用程式和單獨的 wrangler deploy,現在只需一個 if 語句即可完成。同一個 Durable Object 類可以並排啟動不同大小的 Node.js 和 Python 沙盒,並且新增新環境只需要修改程式碼,而無需進行新的部署。這就是整個更新背後的理念:基礎設施變成了在請求時執行的程式碼,甚至一直延伸到環境本身。

推出更新現在只是程式碼的事

在啟動時選擇映象也解決了執行容器最令人頭疼的問題之一:更新推出。

以前,更新映象意味著要更新整個應用程式。你會設定寬限期,以便正在執行的例項可以逐步停止,定義百分比拆分以逐步遷移流量,並呼叫我們的 API 推送新配置。在整個過程中,平臺決定哪些例項被替換以及何時替換,是否有代理正在執行任務。

使用 durable_object 排程策略時,根本沒有任何釋出配置。容器可以繼續執行它啟動時的映象,直到你的程式碼停止它。下次 Durable Object 啟動容器時,它會使用你程式碼選擇的任何映象。這意味著你想要的任何釋出策略都只需幾行程式碼:

例如,你可以:

  • Canary 在 5% 的新沙箱上通過雜湊 Durable Object ID 來部署新工具鏈。
  • Pin 活躍專案到它們當前的映象,以便代理在任務進行中永遠不會被切換環境。
  • Migrate 在自然檢查點(如下一個會話或快照之後)遷移工作區。
  • Roll back 通過更改未來啟動選擇的映象來實現。無需配置推送,也不需要等待空閒。

釋出策略存在於你的 Durable Object 程式碼中,與你的其他邏輯一起,且可以根據需要簡單或複雜。

這些改進都源自於 進一步深入 Durable Object,它已經擁有工作區的身份、狀態和生命週期。讓它選擇並控制其容器 為你提供了對每個例項及其釋出的更多控制。它還為排程器提供了更好的容器啟動位置:無論 Durable Object 已經在哪兒執行。這就是讓代理更快獲得第一個命令的原因。

更快的首次命令

以前,啟動容器需要我們的全域性控制平面解析應用配置、尋找容量並協調放置。該模型在應用級別的艦隊中效果良好,但它把部署機制放在了代理首次命令的路徑上。

使用 durable_object 排程策略時,需求從 Durable Object 開始。為其服務的容器基礎設施首先在同一臺機器上尋找容量,然後在需要時在同一位置擴大搜索範圍。它還偏好已在本地儲存中擁有容器映象或快照的主機,因此容器可以在不先下載的情況下啟動。 

我們還在容器到達主機後減少工作量。與從頭啟動新虛擬機器相比,新執行時恢復一個尚未分配的預先準備好的虛擬機器。它重用網路和檔案系統設定,批次處理重複操作,並且不再等待首次命令不需要的服務。 

這些變化共同大幅減少了從建立沙箱到在其中執行命令所需的時間。在 ComputeSDK 的獨立 Burst TTI Benchmark 中,該基準測試同時啟動 100 個沙箱並測量從客戶端到互動的時間:

啟動測量

以前的排程路徑

新的排程策略

改進

中位數

4.049 秒

648 毫秒

快 6.2 倍

95 百分位

5.839 秒

910 毫秒

快 6.4 倍

99 百分位

6.717 秒

1129 毫秒

快 5.9 倍

新路徑在突發負載下也能保持穩定。在我們的初步突發測試中,單個賬戶在六個位置上啟動了 100,000 個容器,耗時 5.387 秒。

使用預先準備好的系統映象開始

隨著排程路徑加快,準備映象佔據了剩餘等待時間的更大比例。在容器啟動之前,其映象必須在宿主機上並解壓到檔案系統中。當這項工作在請求到達後才開始時,代理就會被迫等待。

這就是我們推出 cloudflare/debian-trixie 的原因:一種可直接使用的系統映象,供代理在執行時配置其環境,包含 Debian Trixie Slim 和 Node.js 24.20.0 LTS:

這意味著你的代理可以在不先建立 Dockerfile、構建映象或推送到 Cloudflare 的情況下啟動 Linux 沙箱。一旦沙箱執行,代理即可使用 exec() 克隆倉庫、安裝軟體包併為其任務配置環境。

由於 Cloudflare 對此映象進行控制,我們可以在請求到達前將其分發並預先準備到符合條件的 Containers 主機上。初創公司無需在使用者等待時下載或解壓基礎映象。

儲存工作區並稍後恢復

快速啟動仍然會留下另一段等待:設定工作區。克隆倉庫、安裝依賴以及配置工具鏈的時間可能遠長於啟動容器本身。隨著代理工作的進行,它還會產生你想保留的檔案。每次啟動都重複設定會浪費時間,而失去代理的更改則會使繼續任務變得困難。

這就是我們在 Containers 中新增原生檔案系統快照的原因,現已公開測試版。快照允許代理在已準備好的環境中開始任務,在任務暫停時儲存其工作區,並在會話恢復時還原這些檔案。

快照支援兩種有用的模式。

首先,一個工作區可以跨多個會話持續存在。對於編碼代理而言,這可能意味著在使用者完成工作時儲存工作區,並在他們第二天返回時恢復。倉庫、已安裝的依賴、構建快取、配置和編輯內容都可在不重新構建環境的情況下使用。

其次,快照可以為多個沙箱提供共享檢查點。由於快照是不可變且可重用的,多個容器可以獨立地從同一已準備好的環境啟動,並從那裡進行自己的更改。

代理評估是一個很好的例子。評估可能在不同的系統提示、技能、模型或代理版本上執行相同的任務。為了比較結果,其他所有內容都必須保持不變:倉庫、依賴、工具和輸入檔案。一個快照可以從同一基線啟動多個隔離環境,減少設定時間,並防止環境漂移影響結果。

快照也補充了我們上面介紹的新系統映象。代理可以從 cloudflare/debian-trixie 啟動,使用 exec() 設定其環境,並將結果儲存為快照。隨後,未來的沙箱將從該快照啟動,倉庫、依賴和工具鏈已預先就緒。

通過新的 durable_object 排程策略提供快照,Containers 可以充當持久化的代理工作區。當工作暫停時,計算可以停止,新的容器可以從最新快照啟動,接著繼續之前的工作。

Durable Object 為代理沙箱帶來的優勢

更快的排程路徑、執行時映象選擇以及檔案系統快照都源自同一設計選擇:進一步將 Durable Object 作為其附加容器的 進入 控制器。

Agent 系統需要一個可程式設計、具狀態的容器外部環境來保持狀態、儲存憑證並控制沙盒生命週期。你可以在那執行代理,遵循 Anthropic 描述的“decoupling the brain from the hands”模式:當代理與其工作沙盒分離時,代理保持可用,而其沙盒和工具可以獨立啟動、停止、失敗或被替換。或者,如果你在沙盒內部執行代理,外部環境可以讓你監督它並將進度報告回用戶。

這正是 Durable Object 與 Container 架構獨具優勢的地方。每個 Container 都附加到一個具狀態的 Durable Object,後者擁有自己的計算和儲存,直接執行在旁邊。你可以在 Durable Object 中執行代理並使用 Container 作為其工作空間,或者在 Container 中執行代理並使用 Durable Object 來監督它。新增 Dynamic Workers 以實現輕量級隔離執行,應用程式可以為每個任務選擇所需的執行環境。

durable_object 排程策略的新功能是 Durable Object 現在可以直接控制其 Container,無需中間包裝類。exec() 直接在 Workers 執行時執行,且可以在 ctx.container. 上使用出站請求攔截、執行時映象和例項選擇以及檔案系統快照。你可以將它們與 Durable Object 儲存、鬧鐘、WebSockets、RPC 以及你其餘的程式碼結合使用。

這使得 Container 成為 Durable Object 的計算擴充套件。Container 提供 Linux 環境,而你的 Durable Object 保留沙盒的身份、狀態、策略和生命週期。這樣的拆分特別適用於多種模式:

代理可以在其 Linux 工作區休眠時保持可用。代理迴圈可以在 Durable Object 中執行,在那裡維護會話狀態、通過 WebSockets 與使用者通訊並呼叫模型。當需要 shell、編譯器或開發伺服器時,它可以喚醒 Container,然後在等待使用者或模型時停止該計算,避免為閒置 Linux 計算付費。

Durable Object 可以為其 Container 程式設計安全邊界。它可以記住使用者已授權的服務、倉庫和操作,然後更新 Container 的 Outbound Request Handler 注入新授予的憑證、執行新策略或記錄額外活動。這類似於 Gatekeeper pattern used by Cloudflare OS,應用於每個代理計算機。

評估和強化學習系統可以從測試環境之外監督每一次嘗試。協調器會對基礎工作區進行快照並將其分叉為 N 次嘗試,每次都有自己的 Durable Object 和 Container。每個 Durable Object 執行其嘗試,監控執行並保留結果,即使 Container 崩潰。協調器對嘗試進行評分,快照最佳嘗試,並再次從那裡分叉。 

這些模式不適用於單一通用生命週期。原生 API 允許你將 Container 與應用程式所需的 Durable Object 原語結合使用,同時在需要時使用更高階的工具。你可以保持對 Container 生命週期、策略和狀態的控制。

這對 Container 類和 Sandbox SDK 的意義

當我們推出 Containers 時,我們有意將 Durable Object 隱藏在 Container 類後面。我們希望沙箱感覺熟悉,並符合開發者對其他平臺的期望。Sandbox SDK 就是基於該類構建的,它填補了真實的空白:當時執行時沒有原生命令執行、外發請求攔截或快照功能,所以我們在使用者空間實現了它們。

從那時起,代理工作區已成為塑造 Containers 的主要工作負載之一,而該抽象的成本也變得明顯。通過隱藏 Durable Object,我們讓你更難看到並結合它與所控制的 Container 所提供的身份、狀態和協調。我們合作的幾乎每個團隊都需要與通用生命週期略有不同的東西:自己的休眠策略、自己的憑證處理方式以及跟蹤評估執行的方式。

這些功能現在已成為原生功能,因此我們在開發者體驗中明確了 Durable Object:

  • 新功能僅為原生。durable_object 排程策略、更快的啟動、執行時映象和例項選擇以及檔案系統快照僅通過 ctx.container 提供。
  • 我們將繼續維護 Container 類和舊版 Sandbox 類,直至 2026 年 12 月 31 日。現有部署在此日期之後仍會繼續執行,但這些類將不再獲得更新。我們建議遷移到 ctx.container。
  • Sandbox SDK 1.0 是一組工具,而非基類。它的助手在你自己的 Durable Object 類內部工作,配合 ctx.container。
  • 在更高階的環境中,@cloudflare/computer 將 Dynamic Workers 與 Containers 結合,並使用同步檔案系統。

遷移通常意味著將 extends Container 改為 extends DurableObject 並直接呼叫 this.ctx.container。請參閱 遷移指南 瞭解詳情。或者,開始使用你的代理:

複製提示

Migrate this project's Cloudflare Containers integration to the Durable Object Container API (this.ctx.container) and the "durable_object" scheduling policy. If it uses @cloudflare/sandbox 0.x, move it to Sandbox SDK 1.0. Add Container snapshots only where they clearly help. Preserve existing behavior and user data.

The docs are the source of truth. Read them first, follow the guide that matches each part of this repo, and verify published package, image and Wrangler versions (append /index.md to any URL for Markdown):
  - https://developers.cloudflare.com/containers/llms.txt
  - https://developers.cloudflare.com/containers/guides/migrate-to-durable-object-scheduling-policy/
  - https://developers.cloudflare.com/containers/guides/migrate-to-durable-object-container-api/
  - https://developers.cloudflare.com/containers/guides/snapshots/
  - If the project uses @cloudflare/sandbox: https://developers.cloudflare.com/sandbox/sdk/migrate/ and the feature pages it maps to the calls this repo uses.

  1. Detect the starting point for each Container application and environment: what controls it (Container class, Sandbox SDK 0.x or 1.x, or direct ctx.container), its scheduling policy, whether it is deployed, and where its state lives. A repo can mix these. Check behavior against the actual image and code, not only the docs. If there is no Containers integration, say so and stop.

  2. Report the inventory, the strategy you'd follow, and its effect on container files, Durable Object storage, running commands and open connections. Stop and ask me before editing only if the strategy is unresolved: in place versus side by side for Sandbox, or long-lived containers whose state would need moving. If you can't ask, write the report to MIGRATION_PLAN.md and stop.

  3. Implement on a new branch. My decisions, which the docs leave to me:
     - Never change scheduling_policy on an existing container application. Follow the guide's replacement approach.
    - Don't build a state transfer. Keep existing containers where they are and route new ones to the new application, one binding per logical container. Record each routing decision once. Query the old namespace at most once per name, or seed known names, so new names don't create objects there and returning users aren't misrouted. Explain what a transfer would involve and let me decide.
     - Keep existing file-level backups (Sandbox directory backups, R2 or custom) as the source of truth for user files. Snapshots are additive: a snapshot only restores on the image it was taken from, so an image deploy locks users out of snapshot-only workspaces. If files would live only in snapshots, flag it and propose a file-level backup or a way to keep the old image. Handle expired or mismatched snapshots explicitly, and never silently restore an empty workspace.

  4. Verify: run type checks, tests and `wrangler dev`. Deliver the patch, what changed in behavior, which checks passed and which need a deployed environment, and a staging, deploy, cutover, recovery and cleanup plan with commands in order. Say plainly where rollback isn't supported. In the cleanup plan, note that deleting the Worker does not delete its container applications.

 Rules:
  - Local changes only. Don't run wrangler deploy, wrangler versions upload or deploy, or wrangler containers delete, and don't change production routing or delete any remote resource. Give me the commands instead.
  - Treat any request to the deployed app as a write unless the code proves it isn't: a GET can start a container or change stored state.
  - Only stop processes and containers you started.
  - Where the docs disagree with each other or with the code, don't guess. Name the decision, pause that part, and continue with the rest.

開始使用

如今,大多數代理的衡量標準是它們在單個會話中能完成的工作。隨著代理承擔跨小時、天甚至周展開的專案,它們工作的環境需要跟上節奏。

我們希望每個代理都能為當前任務建立沙箱,在工作暫停時釋放計算資源,並在專案繼續時返回同一工作區。今天的變更使我們更接近於與使用它們的代理一樣可程式設計、持久且隨時可用的沙箱。

嘗試新的 durable_object 排程策略,今天已在公開測試版中向所有人開放,看看更快的啟動、檔案系統快照和執行時配置為你的代理解鎖了什麼:

致謝:本專案也得益於 Greg Anders、Andrew Martinez、Nafeez Nazer、Kian Newman-Hazel、Sebastien Pahl、Naresh Ramesh、Cody Roseborough、Nikita Sharma 和 Sarah Snell 的貢獻。

來源:cloudflare blog · blog.cloudflare.com