Cloudflare Containers 完全指南:在 Workers 平台上部署容器化应用(含 Wrangler 配置、Container API 与实战模式)

发布时间:2026/9/11 17:42:13
Cloudflare Containers 完全指南:在 Workers 平台上部署容器化应用(含 Wrangler 配置、Container API 与实战模式) Cloudflare Containers 完全指南在 Workers 平台上部署容器化应用含 Wrangler 配置、Container API 与实战模式【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skillsCloudflare Containers 是 Cloudflare Workers 平台上的容器化应用运行方案每个容器本质上都是一个带持久身份persistent identity的 Durable Object支持状态化、长生命周期进程会话、WebSocket、游戏服务、自定义二进制等。本文以仓库内 containers 参考文档 为核心骨架并结合同目录下的 configuration.md、api.md、patterns.md 与 gotchas.md系统讲解从 Wrangler 配置、实例规格、Container 类属性到启动方法、路由决策、WebSocket 转发、优雅关闭、Workflow/Queue 集成以及生产级排错与最佳实践的完整实战方案。⚠️适用前提本文所有内容仅适用于Cloudflare Containers不适用于普通 Cloudflare Workers。且 Containers 目前处于beta阶段API 可能在没有通知的情况下变更无 SLA 保证请务必在生产部署前充分测试。核心概念把容器当作持久化的 Durable Object从架构上看Cloudflare Containers 的设计思想可以浓缩为以下四个要点容器即 Durable Object每个容器都是一个带持久身份persistent identity的 Durable Object可通过getByName(id)或getRandom()访问。这意味着你可以像使用 Durable Object 的命名寻址一样精确或随机地获取某个容器实例。镜像部署模型镜像会被预先拉取pre-fetched到全球各个位置部署时采用**滚动部署rolling**策略而不是 Workers 那种即时生效的部署方式。因此冷启动cold start可维持在 2-3 秒的典型水平。生命周期冷启动2-3s→ running → 达到sleepAfter超时后 → stopped。Containers没有自动扩缩容autoscaling需要靠getRandom()手动做负载均衡。持久身份、临时磁盘容器 ID 持久不变但磁盘在容器停止时会重置ephemeral disk。持久化数据必须使用 Durable Object 存储this.ctx.storage。Beta 状态与账户前提Containers 当前为beta特性需要特别注意API 可能随时变更无通知无 SLA 保证初始阶段仅支持有限区域无自动扩缩容需通过getRandom()手动实现仅支持滚动部署不像 Workers 那样即时生效自定义实例类型custom instance types于2026 年 1 月新增。部署前请先确认认证状态参考仓库级 SKILL.md 的认证要求npx wrangler whoami # 显示账户信息确认已认证快速开始第一个容器 Worker以下是最小可运行的 Containers 示例代码可直接作为项目骨架import { Container } from cloudflare/containers; export class MyContainer extends Container { defaultPort 8080; sleepAfter 30m; } export default { async fetch(request: Request, env: Env) { const container env.MY_CONTAINER.getByName(instance-1); await container.startAndWaitForPorts(); return container.fetch(request); } };关键点自定义类继承自cloudflare/containers的Container通过 Durable Object 绑定env.MY_CONTAINER获取实例使用startAndWaitForPorts()等待端口就绪后再转发请求避免 connection refused。Wrangler 配置声明容器、绑定与迁移wrangler.jsonc 完整配置{ name: my-worker, main: src/index.ts, compatibility_date: 2026-01-10, containers: [ { class_name: MyContainer, image: ./Dockerfile, // Dockerfile 路径或包含 Dockerfile 的目录 instance_type: standard-1, // 预定义或自定义实例类型见下文 max_instances: 10 } ], durable_objects: { bindings: [ { name: MY_CONTAINER, class_name: MyContainer } ] }, migrations: [ { tag: v1, new_sqlite_classes: [MyContainer] // 必须使用 new_sqlite_classes } ] }配置硬性要求image指向 Dockerfile 或包含 Dockerfile 的目录class_name必须与导出的 Container 类名一致max_instances最大并发容器实例数必须同时配置 Durable Objects binding 与 migrations二者缺一不可迁移必须使用new_sqlite_classes容器依赖 SQLite 存储。wrangler.toml 等价格式name my-worker main src/index.ts compatibility_date 2026-01-10 [[containers]] class_name MyContainer image ./Dockerfile instance_type standard-2 max_instances 10 [[durable_objects.bindings]] name MY_CONTAINER class_name MyContainer [[migrations]] tag v1 new_sqlite_classes [MyContainer]两种格式均受支持推荐使用wrangler.jsonc以支持注释并获得更好的 IDE 支持。实例类型Instance Types预定义类型类型vCPU内存磁盘lite1/16256 MiB2 GBbasic1/41 GiB4 GBstandard-11/24 GiB8 GBstandard-216 GiB12 GBstandard-328 GiB16 GBstandard-4412 GiB20 GB{ containers: [ { class_name: MyContainer, image: ./Dockerfile, instance_type: standard-2 // 使用预定义类型 } ] }自定义类型2026 年 1 月新增{ containers: [ { class_name: MyContainer, image: ./Dockerfile, instance_type_custom: { vcpu: 2, // 1-4 vCPU memory_mib: 8192, // 512-12288 MiB最高 12 GiB disk_mib: 16384 // 2048-20480 MiB最高 20 GB } } ] }自定义类型约束每 vCPU 至少 3 GiB 内存每 1 GiB 内存最多 2 GB 磁盘单容器上限4 vCPU、12 GiB 内存、20 GB 磁盘。账户级资源限额资源限额说明总内存所有容器400 GiB所有运行中容器合计总 vCPU所有容器100所有运行中容器合计总磁盘所有容器2 TB所有运行中容器合计每账户镜像存储50 GB已存储的容器镜像Container 类属性详解import { Container } from cloudflare/containers; export class MyContainer extends Container { // 端口配置 defaultPort 8080; // fetch() 调用使用的默认端口 requiredPorts [8080, 9090]; // startAndWaitForPorts() 等待的端口 // 生命周期 sleepAfter 30m; // 无活动超时如 5m、30m、2h // 网络 enableInternet true; // 是否允许出站互联网访问 // 健康检查 pingEndpoint /health; // 健康检查端点路径 // 环境变量 envVars { // 传递给容器的环境变量 NODE_ENV: production, LOG_LEVEL: info }; // 启动 entrypoint [/bin/start.sh]; // 覆盖镜像 entrypoint可选 }属性细节说明defaultPort调用container.fetch()而未显式指定端口时使用的端口。未设置时回退到端口33。requiredPortsstartAndWaitForPorts()返回前必须处于监听状态的端口数组。若未设置defaultPort数组中的第一个端口会被当作默认端口。sleepAfter时长字符串如5m、30m、2h。容器在无活动达到该时长后停止每次请求都会重置该计时器。enableInternet布尔值。为true时容器可发起出站 HTTP/TCP 请求。pingEndpoint健康检查使用的路径应返回 2xx 状态码。envVars环境变量对象会与运行时提供的变量合并见下文。entrypoint字符串数组覆盖镜像的 CMD/ENTRYPOINT。运行时自动注入的环境变量Cloudflare 会自动为容器注入以下环境变量变量说明CLOUDFLARE_APPLICATION_IDWorker 应用 IDCLOUDFLARE_COUNTRY_A2请求来源的两字母国家代码CLOUDFLARE_LOCATIONCloudflare 数据中心位置CLOUDFLARE_REGION区域标识CLOUDFLARE_DURABLE_OBJECT_ID容器的 Durable Object IDContainer 类中自定义的envVars会与这些运行时变量合并若名称冲突自定义变量优先覆盖运行时变量。镜像管理机制分发模型部署前镜像会被预取到全球所有位置从而保证 2-3 秒的典型冷启动。滚动部署与 Workers 的即时生效不同容器部署是逐步滚动的滚动期间旧版本仍继续运行。临时磁盘容器磁盘是临时的每次停止都会重置。持久化必须依赖 Durable Object 存储this.ctx.storage。Container 类 API 全景类定义与核心属性import { Container } from cloudflare/containers; export class MyContainer extends Container { defaultPort 8080; requiredPorts [8080]; sleepAfter 30m; enableInternet true; pingEndpoint /health; envVars {}; entrypoint []; onStart() { /* 容器启动 */ } onStop() { /* 容器停止中 */ } onError(error: Error) { /* 容器错误 */ } onActivityExpired(): boolean { /* 超时回调返回 true 保持存活 */ } async alarm() { /* 定时任务 */ } }路由RoutinggetByName(id)命名实例用于会话亲和session affinity、按用户保存状态。getRandom()随机实例用于无状态服务的负载均衡。const container env.MY_CONTAINER.getByName(user-123); const container env.MY_CONTAINER.getRandom();启动方法Startup Methodsstart()——基础启动8s 超时await container.start(); await container.start({ envVars: { KEY: value } });在进程启动时即返回而非端口就绪时。适用于 fire-and-forget 场景。startAndWaitForPorts()——推荐20s 超时await container.startAndWaitForPorts(); // 使用 requiredPorts await container.startAndWaitForPorts({ ports: [8080, 9090] }); await container.startAndWaitForPorts({ ports: [8080], startOptions: { envVars: { KEY: value } } });在端口开始监听时返回。发起 HTTP/TCP 请求前必须使用。端口解析顺序显式指定的ports→requiredPorts→defaultPort→ 端口 33。waitForPort()——等待特定端口await container.waitForPort(8080); await container.waitForPort(8080, { timeout: 30000 });通信Communicationfetch()——支持 HTTP 与 WebSocket// ✅ 支持 WebSocket 升级 const response await container.fetch(request); const response await container.fetch(http://container/api, { method: POST, body: JSON.stringify({ data: value }) });适用于所有 HTTP 通信尤其是 WebSocket。containerFetch()——仅 HTTP不支持 WebSocket// ❌ 不支持 WebSocket const response await container.containerFetch(request);⚠️ 关键WebSocket 场景必须使用fetch()绝不能使用containerFetch()否则 WebSocket 连接会静默失败。TCP 直连const port this.ctx.container.getTcpPort(8080); const conn port.connect(); await conn.opened; if (request.body) await request.body.pipeTo(conn.writable); return new Response(conn.readable);switchPort()——切换默认端口this.switchPort(8081); // 后续 fetch() 使用该端口生命周期钩子Lifecycle HooksonStart()容器进程启动时调用此时端口可能尚未就绪。运行在blockConcurrencyWhile内——期间不处理并发请求务必保持轻量。onStart() { console.log(Container starting); }onStop()收到 SIGTERM 时调用。SIGTERM 到 SIGKILL 之间有15 分钟窗口用于优雅关闭。onStop() { // 保存状态、关闭连接、冲刷日志 }onError()容器崩溃或启动失败时调用。onError(error: Error) { console.error(Container error:, error); }onActivityExpired()达到sleepAfter超时后调用。返回true保持存活返回false允许停止。onActivityExpired(): boolean { if (this.hasActiveConnections()) return true; // 保持存活 return false; // 允许停止 }定时调度Schedulingexport class ScheduledContainer extends Container { async fetch(request: Request) { await this.schedule(Date.now() 60000); // 1 分钟后 await this.schedule(2026-01-28T00:00:00Z); // ISO 字符串 return new Response(Scheduled); } async alarm() { // 调度触发时调用基于 SQLite重启后依然生效 } }⚠️ 注意使用schedule()辅助方法时不要直接覆盖alarm()因为schedule()内部依赖alarm()实现调度。若直接覆盖定时任务将不会执行。状态检查State Inspection外部检查const state await container.getState(); // state.status: starting | running | stopping | stopped内部检查export class MyContainer extends Container { async fetch(request: Request) { if (this.ctx.container.running) { ... } } }⚠️ 注意外部检查用getState()容器内部检查用ctx.container.running不要混用。路由决策树请求如何到达容器场景方案同一用户/会话 → 同一容器getByName(sessionId)实现会话亲和无状态、需要分散负载getRandom()实现负载均衡每个任务一个容器getByName(jobId) 显式生命周期管理单一全局实例getByName(singleton)何时使用 Containers vs Workers使用 Containers 的场景需要状态化、长生命周期进程会话、WebSocket、游戏运行现有容器化应用Node.js、Python、自定义二进制需要文件系统访问或特定系统依赖需要按用户/会话隔离计算资源。使用 Workers 的场景无状态 HTTP 处理器需要亚毫秒级冷启动自动缩容到零至关重要简单的请求/响应模式。实战模式Patterns会话亲和有状态export class SessionBackend extends Container { defaultPort 3000; sleepAfter 30m; } export default { async fetch(request: Request, env: Env) { const sessionId request.headers.get(X-Session-ID) || crypto.randomUUID(); const container env.SESSION_BACKEND.getByName(sessionId); await container.startAndWaitForPorts(); return container.fetch(request); } };适用用户会话、WebSocket、有状态游戏、按用户缓存。负载均衡无状态export default { async fetch(request: Request, env: Env) { const container env.STATELESS_API.getRandom(); await container.startAndWaitForPorts(); return container.fetch(request); } };适用无状态 HTTP API、CPU 密集型工作、只读查询。单例模式export default { async fetch(request: Request, env: Env) { const container env.GLOBAL_SERVICE.getByName(singleton); await container.startAndWaitForPorts(); return container.fetch(request); } };适用全局缓存、集中式协调器、单一事实来源。WebSocket 转发export default { async fetch(request: Request, env: Env) { if (request.headers.get(Upgrade) websocket) { const sessionId request.headers.get(X-Session-ID) || crypto.randomUUID(); const container env.WS_BACKEND.getByName(sessionId); await container.startAndWaitForPorts(); // ⚠️ 必须使用 fetch()不能使用 containerFetch() return container.fetch(request); } return new Response(Not a WebSocket request, { status: 400 }); } };优雅关闭Graceful Shutdownexport class GracefulContainer extends Container { private connections new SetWebSocket(); onStop() { // 已收到 SIGTERM15 分钟后将被 SIGKILL for (const ws of this.connections) { ws.close(1001, Server shutting down); } this.ctx.storage.put(shutdown-time, Date.now()); } onActivityExpired(): boolean { return this.connections.size 0; // 有连接则保持存活 } }并发请求处理防止重复初始化export class SafeContainer extends Container { private initialized false; async fetch(request: Request) { await this.ctx.blockConcurrencyWhile(async () { if (!this.initialized) { await this.startAndWaitForPorts(); this.initialized true; } }); return super.fetch(request); } }适用一次性初始化、防止并发启动竞态。活动超时续期长任务export class LongRunningContainer extends Container { sleepAfter 5m; async processLongJob(data: unknown) { const interval setInterval(() { this.ctx.storage.put(keepalive, Date.now()); }, 60000); try { await this.doLongWork(data); } finally { clearInterval(interval); } } }适用超过sleepAfter时长的长操作。原理sleepAfter基于请求活动而非内部工作计时通过周期性地 touch storage 续期防止容器被停止。多端口路由export class MultiPortContainer extends Container { requiredPorts [8080, 8081, 9090]; async fetch(request: Request) { const path new URL(request.url).pathname; if (path.startsWith(/grpc)) this.switchPort(8081); else if (path.startsWith(/metrics)) this.switchPort(9090); return super.fetch(request); } }适用多协议服务HTTP gRPC、独立 metrics 端点。Workflow 集成编排容器操作import { WorkflowEntrypoint } from cloudflare:workers; export class ProcessingWorkflow extends WorkflowEntrypoint { async run(event, step) { const container this.env.PROCESSOR.getByName(event.payload.jobId); await step.do(start, async () { await container.startAndWaitForPorts(); }); const result await step.do(process, async () { return container.fetch(/process, { method: POST, body: JSON.stringify(event.payload.data) }).then(r r.json()); }); return result; } }适用多步骤容器操作编排、持久化执行durable execution。Workflows 的详细介绍见 workflows 参考文档。Queue 消费者集成事件驱动处理export default { async queue(batch, env) { for (const msg of batch.messages) { try { const container env.PROCESSOR.getByName(msg.body.jobId); await container.startAndWaitForPorts(); const response await container.fetch(/process, { method: POST, body: JSON.stringify(msg.body) }); response.ok ? msg.ack() : msg.retry(); } catch (err) { console.error(Queue processing error:, err); msg.retry(); } } } };适用异步任务处理、批量操作、事件驱动执行。Queues 的基础用法见 queues 参考文档。关键陷阱Gotchas⚠️ WebSocketfetch() vs containerFetch()问题WebSocket 连接静默失败原因containerFetch()不支持 WebSocket 升级修复WebSocket 一律使用fetch()。// ❌ 错误 return container.containerFetch(request); // ✅ 正确 return container.fetch(request);⚠️ startAndWaitForPorts() vs start()问题start()之后报 connection refused原因start()在进程启动时返回而非端口就绪时修复请求前使用startAndWaitForPorts()。// ❌ 错误 await container.start(); return container.fetch(request); // ✅ 正确 await container.startAndWaitForPorts(); return container.fetch(request);⚠️ 长操作触发活动超时问题长任务执行期间容器被停止原因sleepAfter基于请求活动而非内部工作修复周期性地 touch storage 续期见上文活动超时续期模式。⚠️ 启动竞态条件问题初始化期间出现竞态修复使用blockConcurrencyWhile做原子初始化见上文并发请求处理模式。⚠️ 生命周期钩子阻塞请求问题onStart()期间容器无响应原因钩子运行在blockConcurrencyWhile内不处理并发请求修复钩子保持快速避免长操作。⚠️ 使用 schedule() 时不要覆盖 alarm()问题定时任务不执行原因schedule()内部依赖alarm()修复用schedule()安排任务alarm()交由框架处理在回调中实现任务逻辑。常见错误与解决方案错误原因解决方案Container start timeout容器启动超过start()的 8s 或startAndWaitForPorts()的 20s优化镜像更小的基础镜像、更少的层检查entrypoint确认应用监听正确端口必要时增大超时Port not available端口就绪前就调用了fetch()使用startAndWaitForPorts()Container memory exceeded内存使用超过实例类型上限换更大实例类型standard-2/3/4优化内存使用自定义实例类型Max instances reachedmax_instances槽位全部占用增大max_instances设置合理的sleepAfter用getRandom()分散排查实例泄漏No container instance available达到账户容量上限检查账户限额审视各容器实例类型联系 Cloudflare 支持内存超限时使用自定义实例类型instance_type_custom: { vcpu: 2, memory_mib: 8192 }限制速查表资源限额说明冷启动2-3s镜像已全局预取优雅关闭15 分钟SIGTERM → SIGKILLstart()超时8s进程启动startAndWaitForPorts()超时20s端口就绪单容器最大 vCPU4standard-4 或自定义单容器最大内存12 GiBstandard-4 或自定义单容器最大磁盘20 GB临时磁盘停止即重置账户总内存400 GiB所有容器账户总 vCPU100所有容器账户总磁盘2 TB所有容器镜像存储50 GB每账户磁盘持久性无使用 DO storage最佳实践清单默认使用startAndWaitForPorts()——杜绝端口错误设置合理的sleepAfter——在资源占用与冷启动之间取得平衡WebSocket 使用fetch()——不要用containerFetch()为重启而设计——磁盘是临时的务必实现优雅关闭监控资源——保持在账户限额之内钩子保持快速——它们运行在blockConcurrencyWhile中长操作用续期——周期 touch storage 防止超时停止。阅读顺序与配套参考任务文件新建容器项目README → configuration.md实现容器逻辑README → api.md → patterns.md选择路由模式patterns.md路由章节排查问题gotchas.md生产加固gotchas.md → patterns.md生命周期章节关联主题Durable Objects——Containers 扩展自 Durable Objects理解其状态模型SQLite、KV、Alarms、WebSocket Hibernation有助于把握容器底层行为Workflows——编排容器操作多步骤、自动重试、状态持久化Queues——用队列消息触发容器执行异步任务完整的产品索引与部署流程可参见 cloudflare-deploy SKILL.md。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询