Skip to content
Cloudflare Docs
非官方翻译 - 此文档为非官方中文翻译版本,仅供参考。如有疑问请以 英文官方文档 为准。

开始使用

在本指南中,您将部署一个 Worker,它可以响应最终用户请求向一个或多个容器发出请求。 在此示例中,每个容器都运行一个用 Go 编写的小型 Web 服务器。

此示例 Worker 应该让您了解简单的容器使用,并为更复杂的用例提供起点。

前提条件

确保 Docker 在本地运行

在本指南中,我们将与您的 Worker 代码一起构建和推送容器镜像。默认情况下,此过程使用 Docker 来完成。当您运行 wrangler deploy 时,必须在本地运行 Docker。对于大多数人来说,安装 Docker 的最佳方式是遵循 Docker Desktop 安装文档

您可以通过在终端中运行 docker info 命令来检查 Docker 是否正常运行。如果 Docker 正在运行,该命令将成功执行。如果 Docker 未运行, docker info 命令将挂起或返回包含"Cannot connect to the Docker daemon"消息的错误。

部署您的第一个容器

运行以下命令从启动模板创建并部署带有容器的新 Worker:

Terminal window
npm create cloudflare@latest -- --template=cloudflare/templates/containers-template

当您想要部署 Worker 或容器代码的更改时,可以使用 Wrangler CLI 运行以下命令:

Terminal window
npx wrangler deploy

当您运行 wrangler deploy 时,会发生以下事情:

  • Wrangler 使用 Docker 构建您的容器镜像。
  • Wrangler 将您的镜像推送到自动与您的 Cloudflare 账户集成的容器镜像注册表
  • Wrangler 部署您的 Worker,并配置 Cloudflare 的网络以准备生成您的容器实例

构建和推送通常在第一次部署时耗时最长。后续部署会更快,因为它们会重用缓存的镜像层

检查部署状态

部署后,运行以下命令来显示您的 Cloudflare 账户中的容器列表及其部署状态:

Terminal window
npx wrangler containers list

使用以下命令查看部署到 Cloudflare 注册表的镜像:

Terminal window
npx wrangler containers images list

向容器发出请求

现在,打开您的 Worker 的 URL。它应该类似于 https://hello-containers.YOUR_ACCOUNT_NAME.workers.dev

如果您向路径 /container/1/container/2 发出请求,这些请求会被路由到特定的容器。 "/container/" 后面的每个不同路径都会路由到一个唯一的容器。

如果您向 /lb 发出请求,您将负载均衡请求到随机选择的 3 个容器中的一个。

您可以通过阅读每个请求的输出来确认此行为。

理解代码

现在您已经部署了第一个容器,让我们解释一下您的 Worker 代码、配置文件、容器代码中发生了什么,以及请求是如何路由的。

每个容器都由自己的 Durable Object 支持

传入的请求最初由 Worker 处理,然后传递给启用容器的持久对象(Durable Object)。 为了简化并减少样板代码,Cloudflare 作为 @cloudflare/containers NPM 包的一部分提供了 Container

您不必熟悉 Durable Objects 就能使用容器,但了解基础知识可能会有所帮助。

每个 Durable Object 与单个容器实例一起运行,管理其启动和停止,并且 可以通过端口与容器交互。容器可能在请求它们的 Worker 实例附近运行,但不一定。 有关详细信息,请参阅"如何选择位置"

在简单的应用程序中,Durable Object 可能只是启动容器并将请求代理给它。

在更复杂的应用程序中,拥有启用容器的 Durable Objects 允许您将请求路由到单个有状态的容器 实例,管理容器生命周期,向容器传递自定义启动命令和环境变量,在容器状态更改时运行钩子 等等。

有关更多详细信息,请参阅 Durable Object 容器方法文档Container 类存储库

配置

您的 Wrangler 配置文件 定义了 Worker 和容器的配置:

{
"containers": [
{
"max_instances": 10,
"name": "hello-containers",
"class_name": "MyContainer",
"image": "./Dockerfile"
}
],
"durable_objects": {
"bindings": [
{
"name": "MY_CONTAINER",
"class_name": "MyContainer"
}
]
},
"migrations": [
{
"tag": "v1",
"new_sqlite_classes": [
"MyContainer"
]
}
]
}

关于此配置的要点:

  • image 指向 Dockerfile 或包含 Dockerfile 的目录。
  • class_name 必须是一个 Durable Object 类名
  • max_instances 声明将运行的同时运行容器实例的最大数量。
  • Durable Object 必须使用 new_sqlite_classes 而不是 new_classes

容器镜像

您的容器镜像必须能够在 linux/amd64 架构上运行,除此之外,几乎没有限制。

在您刚刚部署的示例中,它是一个简单的 Golang 服务器,使用 将在 Worker 中设置的 MESSAGE 环境变量和自动生成的 环境变量 CLOUDFLARE_DEPLOYMENT_ID 在端口 8080 上响应请求。

func handler(w http.ResponseWriter, r *http.Request) {
message := os.Getenv("MESSAGE")
instanceId := os.Getenv("CLOUDFLARE_DEPLOYMENT_ID")
fmt.Fprintf(w, "Hi, I'm a container and this is my message: %s, and my instance ID is: %s", message, instanceId)
}

Worker 代码

容器配置

首先注意扩展了 Container 类的 MyContainer

export class MyContainer extends Container {
defaultPort = 8080;
sleepAfter = '10s';
envVars = {
MESSAGE: 'I was passed in via the container class!',
};
override onStart() {
console.log('Container successfully started');
}
override onStop() {
console.log('Container successfully shut down');
}
override onError(error: unknown) {
console.log('Container error:', error);
}
}

这定义了容器的基本配置:

  • defaultPort 设置 fetchcontainerFetch 方法用于与容器通信的端口。它还会阻止 请求,直到容器在此端口上监听。
  • sleepAfter 设置容器在空闲一定时间后进入睡眠的超时时间。
  • envVars 设置容器启动时将传递给容器的环境变量。
  • onStartonStoponError 是分别在容器启动、停止或出错时运行的钩子。

有关更多详细信息和配置选项,请参阅容器类文档

路由到容器

当请求进入 Cloudflare 时,会调用您的 Worker 的 fetch 处理程序。这是处理传入请求的代码。示例代码中的 fetch 处理程序在不同路由上以两种方式启动容器:

  • /container/ 发出请求会为每个路径将请求传递给新容器。这是通过启动新的容器实例来完成的。您可能会注意到 对新路径的第一个请求比后续请求花费更长时间,这是 因为新容器正在启动。

    if (pathname.startsWith("/container")) {
    const id = env.MY_CONTAINER.idFromName(pathname);
    const container = env.MY_CONTAINER.get(id);
    return await container.fetch(request);
    }
  • /lb 发出请求将在多个容器之间负载均衡请求。 这使用了一个简单的 getRandom 辅助方法,该方法从设定数量(在本例中为 3)中随机选择一个 ID,然后路由到该容器实例。您可以用任何您选择实现的路由或负载均衡逻辑替换它:

    if (pathname.startsWith("/lb")) {
    const container = await getRandom(env.MY_CONTAINER, 3);
    return await container.fetch(request);
    }

这允许使用容器的多种方式:

  • 如果您只是想向许多无状态且可互换的容器发送请求, 您应该使用负载均衡。
  • 如果您有有状态服务或需要单独可寻址的 容器,您应该请求特定的容器实例。
  • 如果您正在运行短期作业,希望对容器 生命周期进行细粒度控制,想要参数化容器入口点或环境变量,或 想要将多个容器调用链接在一起,您应该请求特定的 容器实例。

在您的控制面板中查看容器

容器控制面板 向您显示有关容器的有用 信息,包括:

  • 状态和健康状况
  • 指标
  • 日志
  • 指向关联 Workers 和 Durable Objects 的链接

启动 Worker 后,通过单击侧边栏中"Workers & Pages"下的"Containers" 导航到容器控制面板。

下一步

要做更多: