跳转到内容
搜索文档

开始使用

最后更新 查看 MarkdownAgent 设置

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

这个示例 Worker 应该能让您对简单的容器使用有所了解,并为更复杂的用例提供一个起点。

先决条件

确保 Docker 在本地运行

在本指南中,我们将与您的 Worker 代码一起构建并推送容器镜像。默认情况下,此过程使用 Docker ↗ 来完成。

当您运行 wrangler deploy 时,必须在本地运行 Docker。对于大多数人来说,安装 Docker 的最佳方式是按照安装 Docker Desktop 的文档 ↗进行操作。其他工具(如 Colima ↗)也可能有效。

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

部署您的第一个容器

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

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

如果要将代码更改部署到 Worker 或容器代码中,可以使用 Wrangler CLI 运行以下命令:

npx wrangler deploy

运行 wrangler deploy 时,会发生以下情况:

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

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

检查部署状态

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

npx wrangler containers list

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

npx wrangler containers images list

向容器发出请求

现在,打开您的 Worker 的 URL。它应该看起来像 https://hello-containers.<YOUR_WORKERS_SUBDOMAIN>.workers.dev。

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

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

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

了解代码

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

配置

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

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

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

[[migrations]]
tag = "v1"
new_sqlite_classes = [ "MyContainer" ]

关于此配置的要点:

  • image 指向一个 Dockerfile、包含 Dockerfile 的目录,或指向一个完全限定的镜像引用,例如 registry.cloudflare.com/<YOUR_ACCOUNT_ID>/<IMAGE>:<TAG>。
  • 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 设置了 fetch 和 containerFetch 方法将用来与容器通信的端口。它还会阻止请求,直到容器侦听该端口为止。
  • sleepAfter 设置容器在空闲一定时间后休眠的超时。
  • envVars 设置在容器启动时将传递给容器的环境变量。
  • onStart、onStop 和 onError 分别是容器启动、停止或出错时运行的钩子。

Container 类本身扩展了 DurableObject,因此您的子类可以访问完整的 Durable Object API。Durable Object 处理路由、生命周期和持久状态,而容器进程在 Linux VM 中运行您的镜像。这意味着您可以使用 this.ctx.storage 来持久化容器重启后仍然存在的数据,并驻留在容器本身附近。

有关更多详细信息,请参阅 容器类参考 和 低级 Durable Object 容器 API。

路由到容器

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

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

    if (pathname.startsWith("/container")) {
    	const container = env.MY_CONTAINER.getByName(pathname);
    	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);
    }

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

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

在仪表板中查看容器

容器仪表板 ↗向您显示有关您的容器的有用信息,包括:

  • 状态和运行状况
  • 指标
  • 日志

启动 Worker 后,通过在仪表板侧边栏中选择 Workers & Pages > Containers(容器) 前往容器仪表板。

后续步骤

要做更多:

  • 通过更改 Dockerfile 并调用 wrangler deploy 来修改镜像
  • 查看我们的示例以获取更多灵感
  • 查看常见问题解答以了解当前平台的行为和限制

这篇文档对您有帮助吗?