关于 cloudrun-development
面向 CloudBase Run 开发的技能,供需要初始化、部署、检查或排查长期运行后端服务的开发者使用。它侧重部署前的运行模式、数据库网络、凭证和静态资源决策。
主要功能
- 01判断云托管与 HTTP 云函数
- 02规划 SDK 与 TCP 数据库访问
- 03检查网络、入口与凭证配置
- 04排查容器部署和探针故障
适用场景
- 01部署 WebSocket 或 SSE 服务
- 02迁移使用经典数据库驱动的应用
- 03诊断 CloudRun 服务启动失败
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tencentcloudbase/ skills --skill cloudrun-development安装后在 Claude Code 中输入/cloudrun-development确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSE.mdreferences/image-deploy-troubleshooting.mdvpc-and-database.md详细介绍
兄弟技能(仅限本地)
兄弟 CloudBase 技能与此技能一同提供。请使用 ../auth-tool-cloudbase/SKILL.md 这样的本地相对路径。
如果此环境中缺少引用的兄弟技能文件,请让用户安装完整的 CloudBase 插件(或缺少的技能)。不要通过 HTTP 将远程技能或协议 Markdown 获取到 Agent 上下文中。
跨领域协议(编写 HTTP 处理程序或部署镜像前必须阅读):
- 敏感运行时数据保护:
../cloudbase-platform/references/protocols/sensitive-runtime-data-protection.md - 部署门禁:
../cloudbase-platform/references/protocols/deployment-gate.md
CloudBase Run 开发
激活约定
以下情况首先使用此技能
- 任务是初始化、运行、部署、检查或调试 CloudBase Run 服务。
- 请求需要长时间运行的 HTTP 服务、SSE、WebSocket、自定义系统依赖项或容器式部署。
- 任务是在 CloudBase Run 上创建或运行 Agent 服务。
- 任务是迁移使用传统
DATABASE_URL/ TCP 数据库客户端的现有 / GitHub / 第三方后端。 - 服务需要稳定的独立进程(长连接、自定义运行时、VPC 数据库访问)——请参阅下方「云托管 vs HTTP 云函数」决策部分。仅有 Dockerfile 不足以构成强触发条件。
编写代码前阅读(如果)
- 你仍需在 Function 模式和 Container 模式之间做出选择。
- 提示词提到了
queryCloudRun、manageCloudRun、Dockerfile、服务域名或公开/私有访问。 - 应用通过 TCP 依赖 MySQL、PostgreSQL、Redis 或其他 VPC 私有资源 → 先做数据库访问方式决策(优先使用 SDK/网关,见下方「数据库访问方式决策门」);确认必须通过 TCP 直连后 → 还要阅读
references/vpc-and-database.md。 - 你正在为无状态 HTTP 服务选择 CloudRun 还是 HTTP 云函数。
- 服务通过 SDK 调用 CloudBase 资源(PG
app.rdb()、NoSQL、存储、函数)→ 先通过「计算资源访问 CloudBase 的凭证决策门」:凭证由谁签发、如何注入、如何吊销,都必须在编写代码前确定。 - 容器部署失败(
deploy_failed、Pod 未就绪、就绪性检查/探针失败、第三方imageUrl无法保持运行)→ 还要阅读references/image-deploy-troubleshooting.md并遵循下方的容器部署失败 SOP。不要一开始就提高InitialDelaySeconds。
然后还要阅读
- 使用云函数而非 CloudRun ->
../cloud-functions/SKILL.md - Agent SDK 和 AG-UI 相关内容 ->
../cloudbase-agent/SKILL.md - 浏览器调用方的 Web 身份验证 ->
../auth-web-cloudbase/SKILL.md - 现有应用 + TCP 数据库网络 ->
references/vpc-and-database.md - 容器镜像部署失败 / 探针 /
deploy_failed->references/image-deploy-troubleshooting.md - 服务通过 SDK 调用 CloudBase 资源(凭证来源 / 注入 / 吊销)->
../cloud-functions/references/http-function-credentials.md - 关于 CloudRun 费用的计费问题(「没有部署任何内容,为什么还要收费」「免费额度还没用完」)->
../cloud-api-operations/references/recipes/billing-charges-explained.md(赠送额度是总计 3 个月的额度,且只要实例数不为 0,容器就会产生费用)
请勿用于
- 更适合函数模型的简单 Event Function 或 HTTP Function 工作流。
- 没有后端服务的纯前端项目。
- 数据库架构设计任务。
常见错误 / 注意事项
- 只需要普通云函数时,却选择 CloudRun。
- 在容器模式下忘记监听平台提供的
PORT——函数模式下也有相反的情况:在该模式下调用app.listen(),而端口已由框架接管,第二次绑定会因EADDRINUSE失败。 - 猜测凭据环境变量名称。
@cloudbase/node-sdk读取的是CLOUDBASE_APIKEY;臆造的名称(例如TCB_API_KEY)会被静默忽略,直到运行时才表现为“没有凭据”。 - 从本地客户端登录状态(
auth.json、.cloudbase/)中复制服务端凭据,并将其注入已部署的服务。应改用manageAppAuth(action="createApiKey", keyType="api_key")创建密钥,这样密钥才有所有者、轮换方式和可撤销的keyId。参见../cloud-functions/references/http-function-credentials.md。 - 将静态内容打包进镜像——媒体文件、用户上传内容,或按各自节奏更新的资源。 三种情况,一个根本原因:每次部署和每次扩容都会重新构建、推送和拉取镜像,因此任何大型或独立变化的内容都会无谓地拖慢每次部署。
- 媒体文件(
*.mp4、大图、字体)通过COPY . .一并复制进来——一个演示视频就可能让 30 秒的部署变成几分钟。媒体文件应放在云存储中,并通过 URL 引用。添加.dockerignore,排除*.mp4、*.mov、*.zip、*.psd以及public/videos/等媒体目录。 - 将用户上传内容写入容器文件系统——服务是无状态的;本地磁盘上的内容会在下次部署、重启或扩容时消失。上传内容应存入云存储。
- 从镜像提供频繁更新的静态资源——如果资源按自己的节奏变化,每次变化都会触发整个服务重新部署。应从云存储提供这些资源,这样只有 代码 变更时才需要重新部署服务。
- 媒体文件(
- 将 CloudRun 当作有状态应用托管服务,并把重要状态存储在本地磁盘上。
- 认为容器模式支持本地运行。
- 场景只需要私有访问或小程序内部访问时,却默认开放公网访问。
- 部署已有应用时配置了
DATABASE_URL/ MySQL / PostgreSQL / Redis,却遗漏了serverConfig.VpcConf——部署看似成功,随后运行时数据库连接失败。 - 新应用部署默认选 TCP 直连数据库——能通过 SDK/网关访问的数据(PG
app.rdb()、NoSQL、storage)不需要VpcConf,也不需要数据库账号密码;只有迁移类应用(无法替换经典驱动/ORM)才使用 TCP 直连 +VpcConf。参见“数据库访问方式决策门”。 - 混淆
OpenAccessTypes(用户如何访问服务)与VpcConf(服务如何访问 VPC 数据库)。 - 部署到尚未初始化 CloudRun 的环境——在没有大租户记录的环境中调用
CreateCloudRunServer,会静默进入旧版小租户路径,创建错误的小租户服务/版本。首次部署前务必先初始化环境(manageCloudRun(action="initEnv"),tcbr)。现在,manageCloudRun(action="deploy")会阻止在未初始化的环境中创建新服务,并提供指引。 - 使用旧版
tcbCloudRun API(CreateCloudBaseRunResource/DescribeCloudBaseRunResource/DeleteCloudBaseRunResource)——这些接口已弃用,是小租户开放 API,且在callCloudApi中被阻止。CloudRun 始终通过tcbr(CreateCloudRunEnv/CreateCloudRunServer)运行。使用DescribeEnvBaseInfo(必填EnvId)查询单个环境的基本信息/CloudRun 是否已启用——使用manageCloudRun(action="initEnv")开启,并使用queryCloudRun(action="envStatus")轮询状态;使用DescribeCloudRunEnvs(EnvId为可选筛选条件)查询环境列表/资源信息。 - 部署
httpbin/ 请求回显镜像,或返回req.headers/process.env——CloudBase 可能会注入x-cloudbase-context(base64 临时凭据)。回显该内容会泄露账号的云访问权限。请遵循../cloudbase-platform/references/protocols/sensitive-runtime-data-protection.md。 - 看到就绪探针失败 /
deploy_failed后,立即调高InitialDelaySeconds——探针窗口已经约为 N+150 秒;崩溃循环和环回地址绑定问题并非启动缓慢。请遵循容器部署故障 SOP。 - 部署第三方镜像前未阅读其运行文档——缺少
Cmd、绑定地址环境变量或VolumesConf,看起来都与探针失败相同。 - 对
imageUrl部署调用getDeployLog——那是 CODING 构建日志;请使用getProcessLog。 - 把启动横幅当作服务正常运行的证据——拉取两次
getProcessLog并进行比较;如果启动序列重复出现,说明服务处于重启循环。
Minimal checklist
- Choose Function mode or Container mode explicitly.
- Confirm the environment has CloudRun initialized before the first deploy — a brand-new environment must call
CreateCloudRunEnv(tcbr) first; neverCreateCloudRunServeron an uninitialized environment (it falls back to the legacy 小租户 path).manageCloudRun(action="deploy")validates this automatically and blocks new services on uninitialized environments. When blocked, first callmanageCloudRun(action="initEnv", envId=...)(异步开通) and pollqueryCloudRun(action="envStatus")untilStatus=normal, or reconsider an HTTP cloud function to bypass CloudRun entirely. - Confirm whether the service should be public, VPC-only, or mini-program internal (ingress).
- If the app uses TCP databases/caches, resolve and set
VpcConf(egress / private network) before deploy — seereferences/vpc-and-database.md. - Keep the service stateless and externalize durable data.
- Separate static from dynamic: media files, user uploads, and frequently-updated assets live in cloud storage, not in the image. Check what the Dockerfile copies in.
- Settle the credential path for every CloudBase SDK call before writing code — a server API Key issued through
manageAppAuth(action="createApiKey")and injected viaEnvParams, never a key copied out of the local client login state. - Use absolute paths for every local project path.
- Confirm handlers never echo
x-cloudbase-context, full headers, or credential env vars; do not deploy httpbin-style reflectors. - For third-party images, complete the five-item docs checklist (Cmd / port / bind env / volume / health) before deploy.
Overview
Use CloudBase Run when the task needs a deployed backend service rather than a short-lived serverless function.
云托管 vs HTTP 云函数(按需求选,不按文件选)
核心原则:HTTP 云函数优先。只有需求真正需要云托管时才用云托管;有
Dockerfile不等于必须上云托管。
HTTP 云函数更合适(优先):
- 无状态 HTTP 服务,监听
PORT/9000,只做「请求进来 → 处理 → 响应」的响应式逻辑 - 短生命周期请求,无长连接需求(SSE/WebSocket 之外的普通 API、CRUD、转发)
- 标准 runtime 够用(不需要自定义系统依赖、不需要非标准语言)——需要时也能用镜像函数(Custom Image HTTP Function)跑,仍然在函数这条线上
- 部署更快、费用更低(按请求计费,可缩容到 0)、无需初始化云托管环境
- 有
Dockerfile但服务本质是无状态 HTTP → 优先 HTTP 云函数(HTTP Function / Custom Image HTTP Function),不必上云托管
云托管才需要(只有以下之一才选云托管):
- 长连接:WebSocket、SSE 长连接、服务端推送
- 需要常驻的独立进程:后台任务循环、常驻缓存 / 连接池、自管端口的服务
- VPC 内数据库 / Redis 访问(
VpcConf私有网络连通) - Agent 服务(Function mode CloudRun)
- 迁移已有 / GitHub / 第三方应用
语言不是上云托管的条件:非标准语言(Java / Rust / C++ / PHP / .NET 等)或需要自定义系统依赖时,只要服务仍是「请求进来 → 响应」且无长连接,打成镜像用 Custom Image HTTP Function,就还是函数;只有再叠加常驻 / 长连接 / VPC 才上云托管。
决策示例: 一个带 Dockerfile 的 Go/Python HTTP API,无长连接、无自定义系统依赖、不碰 VPC 数据库 → 选 HTTP 云函数而不是云托管;同一份代码若有 WebSocket 长连接 → 才选云托管。
数据库访问方式决策门(部署前必答:SDK 优先,TCP 直连兜底)
核心原则:能用 CloudBase SDK/网关访问的数据,一律优先 SDK 路径。 TCP 直连会引入 VPC、安全组、数据库账号密码三件套,全是部署后才暴露的问题(
ETIMEDOUT、安全组拦截、密码注入),能不碰就不碰。
优先:SDK / 网关路径(无需 VpcConf、无需数据库账号密码)
- CloudBase PG →
app.rdb()(js-sdk v3 / node-sdk,走 PG HTTP 网关;详见../postgresql-development-cloudbase/SKILL.md) - NoSQL →
app.database();对象存储 →app.storage - 新应用 / CloudBase 原生数据 → 数据层直接按 SDK 路径设计,部署时完全不需要 VPC 配置;若只用到这些数据面,还可结合上一节的「HTTP 云函数优先」进一步免掉云托管
仅当以下情况才走 TCP 直连(须完成 references/vpc-and-database.md 全流程):
- 迁移已有 / GitHub / 第三方应用,数据层是经典驱动或 ORM(mysql2、pg、Prisma、SQLAlchemy、WordPress / Ghost 等),改造成 SDK 的成本高或用户明确要求保留
- 需要 SDK 不覆盖的能力(特定 SQL 方言、存储过程、Redis 原生协议等)
决策动作: 扫描到 DATABASE_URL / DB 依赖信号时,先停下来回答「这个数据访问能不能换成 SDK/网关」,再决定是否进入 VPC checklist——不要默认按 TCP 直连方案往下走。
计算资源访问 CloudBase 的凭证决策门(部署前必答)
核心原则:SDK 路径免掉的是数据库账号密码,不是 CloudBase 资源访问凭证。 服务代码要调 CloudBase 资源(PG
app.rdb()/ NoSQL / storage / functions)时,先把凭证来源定下来,再写代码、再部署。
三件事必须先答:
- 谁签发 — CloudBase 服务端 API Key:
manageAppAuth(action="createApiKey", keyType="api_key", keyName="<service>-<env>"),或 CLItcb env apikey create my-key -e env-xxx。不要从本地客户端登录态(auth.json/.cloudbase/)里取一把来用。 - 怎么注入 — 经
serverConfig.EnvParams注入CLOUDBASE_APIKEY(@cloudbase/node-sdk自动读取该变量;显式字段是accessKey)。变量名以官方为准,不要自造。改环境变量时保留已有键值,不要整份覆盖。 - 怎么吊销 — 每个服务一把专用 key,记录
keyName与轮换负责人;下线或轮换时manageAppAuth(action="deleteApiKey", keyId=...)并重新部署。轮换后旧实例里残留的副本不会报错,只会静默失效。
不要假设云托管容器已自动带上可用的 CloudBase 凭证 —— 部署后用一次真实的 SDK 读取验证(验证两次以上,不要只看进程起没起来)。完整步骤、Manager SDK 的腾讯云密钥对路径、环境变量合并的安全写法见 ../cloud-functions/references/http-function-credentials.md。
api_key 是环境级凭证:可绕过 RLS,单环境签发数量有限。不要给每个服务灌同一把 —— 任一实例失陷即整环境失陷。
When CloudRun is a better fit
- Long connections: WebSocket, SSE, server push
- Long-running request handling or persistent service processes
- Custom runtime environments or system libraries
- Arbitrary languages or frameworks
- Stable external service endpoints with elastic scaling
- AI Agent deployment on Function mode CloudRun
- Migrating existing containerized or multi-language apps that need VPC access to databases
Mode selection
| Dimension | Function mode | Container mode |
|---|---|---|
| Best for | Fast start, Node.js service patterns, built-in framework, Agent flows | Existing containers, arbitrary runtimes, custom system dependencies |
| Port model | The function framework binds the platform port itself — your code must not call app.listen() | App must listen on the injected PORT |
| Dockerfile | Not required | Required — but a Dockerfile alone does not mean CloudRun; first check whether the service needs long connections / custom runtime. Stateless HTTP services with a Dockerfile may fit HTTP cloud functions better. |
| Local run through tools | Supported | Not supported |
| Typical use | Streaming APIs, low-latency backend, Agent service | Custom language stack, migrated container app |
如何使用此技能(面向编码 Agent)
-
先选择模式
- 函数模式 -> HTTP/SSE/WebSocket 或 Agent 场景下最快捷的路径
- 容器模式 -> 确实需要 Docker/自定义运行时环境时使用
-
遵循强制运行时规则
- 容器模式:监听注入的
PORT。函数模式:框架会为你绑定端口——绝不要调用app.listen() - 在编写任何 CloudBase SDK 调用之前,先确定凭证管理机制(由谁签发、如何注入、如何撤销)
- 保持服务无状态
- 将持久化数据存放在 DB/存储/缓存中
- 精简依赖和镜像体积——镜像只包含代码和依赖;媒体、用户上传内容和频繁更新的资源应放到云存储中(参见常见错误)
- 遵循资源配比建议:
Mem = 2 × CPU
- 容器模式:监听注入的
-
使用正确的工具
- 读取操作 ->
queryCloudRun - 写入操作 ->
manageCloudRun - 删除操作需要明确确认并设置
force: true - 始终使用绝对
targetPath
- 读取操作 ->
-
遵循部署顺序
- 初始化或下载代码
- 对于全新环境,确保先初始化 CloudRun——在首次部署前调用
manageCloudRun(action="initEnv", envId=...)(异步、幂等);在未初始化的环境中,manageCloudRun(action="deploy")会阻止创建新服务,并提示你调用initEnv - 对于容器模式,验证 Dockerfile
- 扫描 DB/缓存依赖信号(
DATABASE_URL、docker-compose DB 服务、ORM 配置) - 如果需要 TCP DB 访问,在部署前完成
references/vpc-and-database.md中的 VPC 检查清单 - 如可行,先在本地运行
- 配置入口访问模型,并在需要时配置出口
VpcConf - 对于
imageUrl/ 第三方镜像,在部署前完成容器部署失败 SOP 中的五项文档检查清单 - 部署并验证详情输出和 DB 连通性
- 如果部署失败,请遵循容器部署失败 SOP(
references/image-deploy-troubleshooting.md)——文档 →getProcessLog→ 配置;不要从InitialDelaySeconds入手
工具路由
读取操作
queryCloudRun(action="list")-> 列出服务queryCloudRun(action="detail")-> 检查单个服务及其最新部署状态(如有)queryCloudRun(action="templates")-> 查看可用的启动模板queryCloudRun(action="getDeployLog")-> 构建日志(CODING /DescribeCloudRunBuildLog)。仅在云端源码构建时有意义;已有镜像部署(imageUrl)没有构建过程,不要用它诊断镜像部署失败。未登录 CODING 的账号会报错(例如User not created or may not qcloud user)queryCloudRun(action="getProcessLog")-> 运行日志(tcbr/DescribeCloudRunProcessLog)。返回部署阶段步骤(如create_version_check_vpc/create_eks_virtual_service/check_eks_virtual_service)以及容器启动/运行日志(s6-overlay、应用进程、readiness probe 失败原因)。镜像部署与源码构建均可使用,不依赖 CODING。参数:detailServerName/serverName+ 可选runId(不传则获取最新部署的RunId;也可从detail/getDeployRecords的latestDeploy.RunId获取RunId)queryCloudRun(action="getDeployRecords")-> 列出部署记录(按时间从新到旧;包含BuildId/RunId/FlowRatio/Status)——在流量操作前用于查看发布历史和回滚上下文queryCloudRun(action="envStatus")-> 检查环境的 CloudRun 是否已开通及其开通过程状态(Status=creating表示正在开通 /normal表示已开通)——在initEnv后用于轮询进度,或在deploy前确认已就绪queryCloudRun(action="getManageTask")-> 发布任务状态(tcbr/DescribeServerManageTask)。返回taskId/taskStatus和最新部署记录状态latestDeployStatus。用于两种情况:遇到「已有部署发布任务运行中」时,先确认任务是否确实在推进;以及部署长时间没有进展时,区分「任务仍在推进」和「任务已卡住」。不知道任务状态时,不要反复重试 deploy
日志查询 SOP(构建日志 vs 运行日志)
排查部署失败时,必须区分两类日志,不要只用 getDeployLog:
- 云端源码构建(传入
targetPath,走 CODING 构建)- 先用
queryCloudRun(action="getDeployLog", detailServerName=..., buildId=...)查询构建日志(编译/打包失败) - 再用
queryCloudRun(action="getProcessLog", detailServerName=..., runId=...)查询运行日志(部署步骤 + 容器启动/健康检查)
- 先用
- 已有镜像部署(传入
imageUrl、DeployType=image)- 跳过
getDeployLog(没有构建过程;且依赖 CODING,未登录会直接失败) - 直接用
queryCloudRun(action="detail")或getDeployRecords获取latestDeploy.RunId,再用getProcessLog查询运行日志
- 跳过
{
"action": "getProcessLog",
"detailServerName": "my-svc",
"runId": "<from latestDeploy.RunId>"
}
部署任务 SOP(遇到「已有部署发布任务运行中」时)
manageCloudRun(action="deploy") 报错「已有部署发布任务运行中」/ already has a deploy task running 时,不要盲目重试,也不要反复修改 Dockerfile / serverConfig —— 先确认任务的实际状态:
queryCloudRun(action="getManageTask", detailServerName=...)→ 查看taskId/taskStatus/latestDeployStatusqueryCloudRun(action="getProcessLog")→ 间隔 20–40 秒拉取两次并进行对比,确认部署阶段的步骤是否仍在推进- 根据结果分支处理:
| 观察情况 | 操作 |
|---|---|
taskStatus 仍为运行态,部署步骤有推进 | 继续等待,不要重新发送 deploy |
| 任务已结束(非运行态),但 deploy 仍被拒绝 | 此时才考虑重试 |
任务长时间停留在非终态,版本也停在 creating 没有变化 | 记录 taskId / latestDeployStatus / 时间范围作为证据,不要空转重试 |
force=true 无法解决此问题:它只会跳过本工具的确认提示,不会取消或覆盖服务端已有的发布任务 —— 把它当作「强制覆盖」只会白白失败一次。
日志排查顺序(构建日志 vs 运行日志、先查日志再查配置)见上面的 日志查询 SOP 与 容器部署失败 SOP。
写操作
manageCloudRun(action="initEnv")-> 为环境打开(初始化)CloudRun — 异步、幂等(Status=normal→ 已打开,不会重新创建)。用于全新环境首次部署前,或deploy因「尚未初始化云托管」而受阻时。参数:envId(默认为已配置的环境)、packageType(默认Trial)。轮询queryCloudRun(action="envStatus"),直到Status=normal。manageCloudRun(action="init")-> 创建本地项目manageCloudRun(action="download")-> 拉取远程代码manageCloudRun(action="run")-> Function 模式下本地运行manageCloudRun(action="deploy")-> 触发部署 + 等待注册完成(轻量等待)(不会一直等待完整构建;如果不需要buildId,传入waitRegistration=false可跳过这段等待)。返回buildId/runId/taskId+ 根据 DeployType 提供的next_step:source → 先调用getDeployLog,再调用getProcessLog;image(imageUrl,BuildId 通常为0)→ 跳过getDeployLog,通过getDeployRecords/detail获取RunId,再调用getProcessLog。请遵循返回的next_step—— 不要总是轮询构建日志。对于已有服务:RMW 会保留远程 VpcConf / EnvParams 键 / OpenAccessTypes;对于新服务,会自动验证环境的 CloudRun 是否已初始化 —— 如果尚未初始化,部署会受阻,并提示先调用initEnvmanageCloudRun(action="updateConfig")-> 仅更新配置(不上传代码;VPC / EnvParams / 扩缩容 / 访问类型)manageCloudRun(action="traffic")-> 流量管理 / 灰度发布(与tcb cloudrun traffic保持一致):trafficOp="set"调整稳定版/灰度版的流量比例(stablePercent+canaryPercent必须等于 100,例如 90/10);trafficOp="promote"将灰度版本提升为全量发布(100%,关闭灰度发布,不可逆);trafficOp="rollback"回滚到上一稳定版本(停止正在发布的灰度版本)。先检查queryCloudRun(action="getDeployRecords"),了解当前版本和流量情况manageCloudRun(action="delete")-> 删除服务manageCloudRun(action="createAgent")-> 创建 Agent 服务
Deploying an existing image (imageUrl)
已有一个现成镜像(本地构建好、或第三方发布)时,不需要本地源码目录,直接
manageCloudRun(action="deploy")传入imageUrl即可,走DeployType="image"(容器型)部署,targetPath可省略。若用户明确提到使用某个镜像或无需重新构建代码,必须传 imageUrl,不要仅因本地有源码目录就回退到源码构建。
决策路径(直填 vs 本地中转):
- 公网匿名可拉取(如
ccr.ccs.tencentyun.com/...、公开 Docker Hub 镜像)→ 直填 imageUrl:manageCloudRun(action="deploy", serverName=..., imageUrl="ccr.ccs.tencentyun.com/ns/img:v1", serverConfig={...})。CloudBase 会直接拉取该 registry 地址构建部署。若docker.io/ Docker Hub 在节点上反复拉取失败,不要空转重试:改用 DockerfileFROM <public-image>+targetPath源码构建(CODING 拉公网镜像,产物进 CCR 内网拉取)。见下方 SOP 第 4 步。 - 私有 / 需登录的 registry(
ghcr.io、私有 ECR/Harbor 等)→ 本地中转到 CCR:
然后把docker pull ghcr.io/example/app:latest docker tag ghcr.io/example/app:latest ccr.ccs.tencentyun.com/<ns>/app:latest docker login ccr.ccs.tencentyun.com docker push ccr.ccs.tencentyun.com/<ns>/app:latestccr.ccs.tencentyun.com/<ns>/app:latest作为imageUrl传入。中转只解决拉取,不能替代镜像文档里的启动命令 / 环境变量 / 数据目录。
与 initEnv 联动: 镜像部署同样要求环境已开通云托管。新环境首次部署前先 manageCloudRun(action="initEnv", envId=...),并用 queryCloudRun(action="envStatus") 轮询到 Status=normal;未开通时 deploy 会被拦截并引导先 initEnv。
示例:
{
"action": "deploy",
"serverName": "my-image-svc",
"imageUrl": "ccr.ccs.tencentyun.com/ns/app:latest",
"serverConfig": {
"OpenAccessTypes": ["PUBLIC"],
"Cpu": 0.5,
"Mem": 1,
"MinNum": 1,
"MaxNum": 3,
"Port": 8080,
"Cmd": ["node", "server.js"],
"EnvParams": "{\"PORT\":\"8080\",\"BIND_HOST\":\"0.0.0.0\"}"
}
}
Port / Cmd / EnvParams 必须来自镜像官方文档的五要素清单,不要套用 3000 或省略启动命令。第三方镜像的完整对照见 references/image-deploy-troubleshooting.md 附录。
部署后:manageCloudRun(deploy) 对镜像返回的 next_step 默认指向 getProcessLog(或先 getDeployRecords 取 RunId),不要改去调 getDeployLog。也可用 queryCloudRun(action="detail") 查看 imageInfo(镜像地址与部署类型)。镜像部署失败排查走下方 SOP。
Container deploy failure SOP
顺序:先查镜像官方文档 → 再查运行日志 → 最后才动配置。禁止一看到 probe failed / deploy_failed 就调 InitialDelaySeconds。
详情与案例:references/image-deploy-troubleshooting.md。
1. 部署前:从镜像官方文档确认五要素
不要靠 Docker Hub tag 或「常见默认值」猜。部署前必须确认:
- 启动命令 EntryPoint / Cmd(进程如何前台常驻)→
serverConfig.EntryPoint/Cmd - 服务端口(进程真正 bind 的端口;不要假设 80/3000,也不要假设镜像尊重
PORT)→serverConfig.Port - 对外监听环境变量(必须
0.0.0.0而不是127.0.0.1、功能开关默认关闭等)→EnvParams - 数据目录挂载 →
serverConfig.VolumesConf - 健康端点(CloudRun readiness 探的是服务端口,不是任意 HTTP path)
缺任何一项再部署,失败看起来都会像「健康检查失败」。
2. 部署失败:用 getProcessLog 定性
镜像部署(imageUrl)跳过 getDeployLog(那是云端源码构建的构建日志)。从 detail / getDeployRecords 取 RunId,再 queryCloudRun(action="getProcessLog")。
启动日志存在 ≠ 服务正常运行。 banner、s6/tini 行、sidecar "listening" 都不能证明探针目标已起来。
两次日志对比判活: 隔 20–40 秒再拉一次 getProcessLog。
| 观察 | 定性 |
|---|---|
只有调度/创建步骤(create_eks_*),没有容器 stdout | Pod 调度中 / 镜像拉取 |
| 同一段启动 banner / PID 1 行重复出现(时间戳在走、内容几乎一样) | 容器启动即退出 / 重启循环 |
进程还在,但 listen 在 127.0.0.1 或端口 ≠ serverConfig.Port | 端口 / 绑定地址问题 |
| 两次拉取是同一条启动过程在往后打日志,banner 不重复 | 才可能是启动慢 |
3. Readiness probe 真实机制(严禁先调延迟)
部署步骤完成后:先等 N 秒(InitialDelaySeconds),再大约 每 5 秒 探一次服务端口,连续约 30 次全失败 才判本次部署失败。窗口 ≈ N+150s。不是「N 秒后立即失败」。
- 禁止: 看到 probe failed 就把 N 改成 120。崩溃循环和 loopback 绑定不会因为 N 变大而好。
- 允许调大 N 仅当: 两次日志证明同一个进程还在一次性初始化(JVM 预热、迁移)且尚未 listen。
4. 公网镜像(docker.io)反复失败 → Dockerfile 源码构建
节点直连 Docker Hub 反复失败时,不要空转 imageUrl。写:
FROM docker.io/example/app:latest
用 targetPath 走云端源码构建:CODING 构建机拉公网镜像,产物进 CCR,云托管节点内网拉取。这只解决拉取拓扑,不替代第 1 步的 Cmd / 环境变量 / 卷。
5. Supervisor 镜像(s6 / tini / supervisord)启动即退出
PID 1 往往是监督进程,不是 HTTP 应用。用两次日志找子进程重启风暴。若镜像 issue 记录了 PID 1 / pgrep -f 误匹配,按文档 workaround(绝对路径 Cmd、关闭 supervise),不要调探针延迟。示例见 reference 附录。
Access guidance
- Web/public scenarios -> enable PUBLIC ingress intentionally and pair it with the right auth flow.
- Mini Program -> prefer internal direct connection and avoid unnecessary public exposure.
- Private ingress scenarios -> keep public access off unless the product requirement clearly needs it.
- Database / Redis in a VPC -> this is not solved by
OpenAccessTypes. You must setserverConfig.VpcConfand use the database private address. Readreferences/vpc-and-database.md.
Quick examples
Initialize
{ "action": "init", "serverName": "my-svc", "targetPath": "/abs/ws/my-svc" }
Local run (Function mode)
{ "action": "run", "serverName": "my-svc", "targetPath": "/abs/ws/my-svc", "runOptions": { "port": 3000 } }
Deploy (no VPC-private dependencies)
{
"action": "deploy",
"serverName": "my-svc",
"targetPath": "/abs/ws/my-svc",
"serverConfig": {
"OpenAccessTypes": ["PUBLIC"],
"Cpu": 0.5,
"Mem": 1,
"MinNum": 1,
"MaxNum": 5
}
}
部署(连接到 MySQL / PostgreSQL / Redis 的现有应用,通过 TCP 连接)
{
"action": "deploy",
"serverName": "my-existing-app",
"targetPath": "/abs/ws/my-existing-app",
"serverConfig": {
"OpenAccessTypes": ["PUBLIC"],
"Cpu": 0.5,
"Mem": 1,
"MinNum": 1,
"MaxNum": 5,
"EnvParams": "{\"DATABASE_URL\":\"postgres://user:[email protected]:5432/app\"}",
"VpcConf": {
"VpcId": "vpc-xxxxxxxx",
"SubnetId": "subnet-xxxxxxxx"
}
}
}
有效的 OpenAccessTypes 值:OA(办公网访问)、PUBLIC(公网访问)、MINIAPP(小程序访问)、VPC(VPC 访问)。需要公开 HTTPS 访问的 Web 应用请使用 PUBLIC。
如果希望降低冷启动延迟,建议将 MinNum: 1 设为默认值。如果用户明确更看重低成本,并且接受更多冷启动,请说明其中的权衡,并允许他们将 MinNum 降至 0。
最佳实践
- 尽可能优先使用 PRIVATE/VPC 或小程序内部入口。
- 对于 TCP 数据库访问,始终将私有数据库 URL 与
VpcConf配套使用,并确保二者位于数据库所在的同一 VPC/地域。 - 使用环境变量存放机密信息和各环境的配置——仅在服务端读取;绝不要在 HTTP 响应中返回这些信息。CloudBase API Keys 应通过
manageAppAuth(action="createApiKey")创建,而不是从本地客户端登录文件中获取。 - 在部署前后使用
queryCloudRun(action="detail")验证配置。 - 尽量减少启动时执行的工作,以降低冷启动的影响。
- 对于 Agent 场景,请使用 Agent SDK 技能了解协议和适配器详情,不要在此处重复说明。
- 对于冒烟测试,请返回固定的
{ "ok": true }/ 健康状态负载——绝不要部署 httpbin 或任何会回显请求头的服务。
故障排查提示
- 访问失败 -> 检查入口访问类型、域名设置,以及实例是否已缩容至零。
- 部署因“尚未初始化云托管 / not initialized”而被阻止 -> 必须先为环境启用 CloudRun:调用
manageCloudRun(action="initEnv", envId=...)(异步开通),并轮询queryCloudRun(action="envStatus"),直至Status=normal;或者打开控制台环境 → 云托管 → 开通。对于无状态 HTTP 服务,可以考虑完全改用 HTTP 云函数,而不是 CloudRun。 - 部署失败 -> 按照上文的容器部署失败 SOP(以及
references/image-deploy-troubleshooting.md)操作:镜像部署会跳过getDeployLog,仅使用getProcessLog;通过两次拉取日志区分调度问题、端口问题和启动即退出问题。在日志证明初始化确实缓慢之前,不要调高InitialDelaySeconds。同时检查 Dockerfile(源码)和 CPU/内存比例。 - 部署因“a deploy task is already running” /「已有部署发布任务运行中」而被拒绝 -> 首先使用
queryCloudRun(action="getManageTask")读取实际任务状态。不要盲目重试,也不要设置force=true期待覆盖——它只会跳过此工具的确认提示。请参阅上文的部署任务 SOP。 - 部署已被接受,但版本一直处于
creating状态 -> 使用queryCloudRun(action="getManageTask")检查latestDeployStatus和taskStatus,然后使用getProcessLog查看部署阶段的步骤。只有在日志确实指向代码或配置问题时,才修改 Dockerfile / serverConfig。 - 本地运行失败 -> 请记住,本地运行工具仅支持 Function 模式。
- 性能问题 -> 减少依赖、优化初始化,并调整最小实例数。
- 部署成功后仍无法连接数据库 / Redis -> 几乎总是缺少或配置错误的
VpcConf、私有主机地址错误或安全组配置错误。重写应用代码之前,请先按照references/vpc-and-database.md操作。 - 服务中的 CloudBase SDK 调用因凭据缺失 / 无效而失败 -> 跳过了上述凭据检查,或者变量名不是官方名称。使用
manageAppAuth(action="createApiKey")创建密钥,通过EnvParams将其注入为CLOUDBASE_APIKEY,重新部署,然后验证实际读取。请参阅../cloud-functions/references/http-function-credentials.md。
参考索引
所有打包的参考文件(技能 lint 可达性检查所必需):