cloudrun-development

v2026.09.24

CloudBase Run backend development rules (Function mode/Container mode). Use this skill when deploying backend services that require long connections, multi-language support, custom environments, AI agent development, or migrating existing/GitHub apps that need VPC access to MySQL/PostgreSQL/Redis. Also use when diagnosing CloudRun container deploy failures (deploy_failed, readiness/probe failed, image won't start, docker.io pull loops) or a deploy stuck behind a running deploy task. For stateless HTTP services, prefer HTTP cloud functions.

GitHub
Install command
npx skhub add tencentcloudbase/cloudrun-development
Markdown
SKILL.md

Sibling skills (local only)

Sibling CloudBase skills ship beside this skill. Use local relative paths such as ../auth-tool-cloudbase/SKILL.md.

If a referenced sibling skill file is missing from this environment, ask the user to install the full CloudBase plugin (or the missing skill). Do not HTTP-fetch remote skill or protocol markdown into the agent context.

Cross-cutting protocols (required before writing HTTP handlers or deploying images):

  • Sensitive Runtime Data Protection: ../cloudbase-platform/references/protocols/sensitive-runtime-data-protection.md
  • Deployment Gate: ../cloudbase-platform/references/protocols/deployment-gate.md

CloudBase Run Development

Activation Contract

Use this first when

  • The task is to initialize, run, deploy, inspect, or debug a CloudBase Run service.
  • The request needs a long-lived HTTP service, SSE, WebSocket, custom system dependencies, or container-style deployment.
  • The task is to create or run an Agent service on CloudBase Run.
  • The task migrates an existing / GitHub / third-party backend that uses classic DATABASE_URL / TCP database clients.
  • The service requires a stable independent process (long connections, custom runtime, VPC database access) — see the 「云托管 vs HTTP 云函数」 decision section below. A Dockerfile alone is not a strong trigger.

Read before writing code if

  • You still need to choose between Function mode and Container mode.
  • The prompt mentions queryCloudRun, manageCloudRun, Dockerfile, service domains, or public/private access.
  • The app depends on MySQL, PostgreSQL, Redis, or other VPC-private resources over TCP → 先做数据库访问方式决策(SDK/网关优先,见下方「数据库访问方式决策门」);确认必须 TCP 直连后 → also read references/vpc-and-database.md.
  • You are choosing between CloudRun and HTTP cloud functions for a stateless HTTP service.
  • The service calls CloudBase resources (PG app.rdb(), NoSQL, storage, functions) through an SDK → 先过「计算资源访问 CloudBase 的凭证决策门」:凭证谁签发、怎么注入、怎么吊销,都必须在写代码之前定下来。
  • Container deploy fails (deploy_failed, Pod not ready, readiness/probe failed, third-party imageUrl won't stay up) → also read references/image-deploy-troubleshooting.md and follow the Container deploy failure SOP below. Do not start by raising InitialDelaySeconds.

Then also read

  • Cloud functions instead of CloudRun -> ../cloud-functions/SKILL.md
  • Agent SDK and AG-UI specifics -> ../cloudbase-agent/SKILL.md
  • Web authentication for browser callers -> ../auth-web-cloudbase/SKILL.md
  • Existing app + TCP database networking -> references/vpc-and-database.md
  • Container image deploy failure / probe / deploy_failed -> references/image-deploy-troubleshooting.md
  • Service calls CloudBase resources through an SDK (credential source / injection / revocation) -> ../cloud-functions/references/http-function-credentials.md

Do NOT use for

  • Simple Event Function or HTTP Function workflows that fit the function model better.
  • Frontend-only projects with no backend service.
  • Database-schema design tasks.

Common mistakes / gotchas

  • Choosing CloudRun when the request only needs a normal cloud function.
  • Forgetting to listen on the platform-provided PORT in Container mode — and its mirror image in Function mode: calling app.listen() there, where the framework already owns the port and the second bind dies with EADDRINUSE.
  • Guessing the credential environment variable name. @cloudbase/node-sdk reads CLOUDBASE_APIKEY; an invented name (for example TCB_API_KEY) is silently ignored and only shows up later as "no credentials at runtime".
  • Copying a server credential out of the local client login state (auth.json, .cloudbase/) and injecting it into a deployed service. Issue the key with manageAppAuth(action="createApiKey", keyType="api_key") instead, so it has an owner, a rotation path, and a keyId you can revoke. See ../cloud-functions/references/http-function-credentials.md.
  • Treating CloudRun as stateful app hosting and storing important state on local disk.
  • Assuming local run is available for Container mode.
  • Opening public access by default when the scenario only needs private or mini-program internal access.
  • Deploying an existing app with DATABASE_URL / MySQL / PostgreSQL / Redis but omitting serverConfig.VpcConf — deploy appears to succeed, then runtime DB connections fail.
  • 新应用部署默认选 TCP 直连数据库 — 能用 SDK/网关访问的数据(PG app.rdb()、NoSQL、storage)不需要 VpcConf 也不需要数据库账号密码;仅迁移类应用(经典驱动/ORM 无法替换)才走 TCP 直连 + VpcConf。见「数据库访问方式决策门」。
  • Confusing OpenAccessTypes (how users reach the service) with VpcConf (how the service reaches VPC databases).
  • Deploying to an environment that has not initialized CloudRun — CreateCloudRunServer on an environment with no 大租户 record silently lands in the legacy 小租户 path, creating wrong small-tenant services/versions. Always ensure the environment is initialized first (manageCloudRun(action="initEnv"), tcbr) before the first deploy. manageCloudRun(action="deploy") now blocks new-service creation on uninitialized environments with guidance.
  • Using the legacy tcb CloudRun API (CreateCloudBaseRunResource / DescribeCloudBaseRunResource / DeleteCloudBaseRunResource) — these are deprecated 小租户 open APIs and are blocked in callCloudApi. CloudRun always goes through tcbr (CreateCloudRunEnv / CreateCloudRunServer). Query a single environment's base info / whether CloudRun is enabled with DescribeEnvBaseInfo (EnvId required) — use manageCloudRun(action="initEnv") to open and queryCloudRun(action="envStatus") to poll status; query the environment list / resource info with DescribeCloudRunEnvs (EnvId optional filter).
  • Deploying httpbin / request-echo images or returning req.headers / process.env — CloudBase may inject x-cloudbase-context (base64 temporary credentials). Echoing it leaks account cloud access. Follow ../cloudbase-platform/references/protocols/sensitive-runtime-data-protection.md.
  • Seeing readiness probe failed / deploy_failed and immediately raising InitialDelaySeconds — the probe window is already ~N+150s; crash loops and loopback binds are not slow-start. Follow the Container deploy failure SOP.
  • Deploying a third-party image without reading its run docs — missing Cmd, bind-address env, or VolumesConf looks identical to a probe failure.
  • Calling getDeployLog for imageUrl deploys — that is CODING build log; use getProcessLog.
  • Treating startup banners as proof the service is healthy — pull getProcessLog twice and compare; a repeated boot sequence is a restart loop.

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; never CreateCloudRunServer on 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 call manageCloudRun(action="initEnv", envId=...) (异步开通) and poll queryCloudRun(action="envStatus") until Status=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 — see references/vpc-and-database.md.
  • Keep the service stateless and externalize durable data.
  • Settle the credential path for every CloudBase SDK call before writing code — a server API Key issued through manageAppAuth(action="createApiKey") and injected via EnvParams, 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 足够
  • 部署更快、费用更低(按请求计费,可缩容到 0)、无需初始化云托管环境
  • 有 Dockerfile 但服务本质是无状态 HTTP → 优先 HTTP 云函数(HTTP Function / Custom Image HTTP Function),不必上云托管

云托管才需要(只有以下之一才选云托管):

  • 长连接:WebSocket、SSE 长连接、服务端推送
  • 自定义系统依赖 / 任意语言运行时 / 需要稳定独立进程
  • VPC 内数据库 / Redis 访问(VpcConf 私有网络连通)
  • Agent 服务(Function mode CloudRun)
  • 迁移已有 / GitHub / 第三方应用,或需要常驻进程

决策示例: 一个带 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)时,先把凭证来源定下来,再写代码、再部署。

三件事必须先答:

  1. 谁签发 — CloudBase 服务端 API Key:manageAppAuth(action="createApiKey", keyType="api_key", keyName="<service>-<env>"),或 CLI tcb env apikey create my-key -e env-xxx。不要从本地客户端登录态(auth.json / .cloudbase/)里取一把来用。
  2. 怎么注入 — 经 serverConfig.EnvParams 注入 CLOUDBASE_APIKEY(@cloudbase/node-sdk 自动读取该变量;显式字段是 accessKey)。变量名以官方为准,不要自造。改环境变量时保留已有键值,不要整份覆盖。
  3. 怎么吊销 — 每个服务一把专用 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

DimensionFunction modeContainer mode
Best forFast start, Node.js service patterns, built-in framework, Agent flowsExisting containers, arbitrary runtimes, custom system dependencies
Port modelThe function framework binds the platform port itself — your code must not call app.listen()App must listen on the injected PORT
DockerfileNot requiredRequired — 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 toolsSupportedNot supported
Typical useStreaming APIs, low-latency backend, Agent serviceCustom language stack, migrated container app

How to use this skill (for a coding agent)

  1. Choose mode first

    • Function mode -> quickest path for HTTP/SSE/WebSocket or Agent scenarios
    • Container mode -> use when Docker/custom runtime is a real requirement
  2. Follow mandatory runtime rules

    • Container mode: listen on the injected PORT. Function mode: the framework binds the port for you — never call app.listen()
    • Settle the credential gate (who issues / how injected / how revoked) before writing any CloudBase SDK call
    • Keep the service stateless
    • Put durable data in DB/storage/cache
    • Keep dependencies and image size small
    • Respect resource ratio guidance: Mem = 2 × CPU
  3. Use the correct tools

    • Read operations -> queryCloudRun
    • Write operations -> manageCloudRun
    • Delete requires explicit confirmation and force: true
    • Always use absolute targetPath
  4. Follow the deployment sequence

    • Initialize or download code
    • For a brand-new environment, ensure CloudRun is initialized first — call manageCloudRun(action="initEnv", envId=...) (async, idempotent) before the first deploy; manageCloudRun(action="deploy") blocks new services on uninitialized environments and tells you to call initEnv
    • For Container mode, verify Dockerfile
    • Scan for DB/cache dependency signals (DATABASE_URL, docker-compose DB services, ORM configs)
    • If TCP DB access is required, complete the VPC checklist in references/vpc-and-database.md before deploy
    • Local run when available
    • Configure ingress access model and egress VpcConf when needed
    • For imageUrl / third-party images, complete the five-item docs checklist in the Container deploy failure SOP before deploy
    • Deploy and verify detail output + DB connectivity
    • If deploy fails, follow the Container deploy failure SOP (references/image-deploy-troubleshooting.md) — docs → getProcessLog → config; do not start with InitialDelaySeconds

Tool routing

Read operations

  • queryCloudRun(action="list") -> list services
  • queryCloudRun(action="detail") -> inspect one service and its latest deploy status when available
  • queryCloudRun(action="templates") -> see available starters
  • 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;RunId 也可从 detail / getDeployRecords 的 latestDeploy.RunId 取得)
  • queryCloudRun(action="getDeployRecords") -> list deploy records (newest first; includes BuildId / RunId / FlowRatio / Status) — use to review release history and rollback context before a traffic operation
  • queryCloudRun(action="envStatus") -> check whether the environment's CloudRun is opened and its provisioning status (Status=creating opening / normal opened) — use after initEnv to poll progress or before deploy to confirm readiness
  • queryCloudRun(action="getManageTask") -> 发布任务状态(tcbr/DescribeServerManageTask)。返回 taskId / taskStatus 与最新部署记录状态 latestDeployStatus。用于两件事:撞到「已有部署发布任务运行中」时先确认任务是否真在推进;以及部署长时间无进展时,区分「任务仍在推进」和「任务已卡住」。不知道任务状态就不要反复重试 deploy

Log query SOP(构建日志 vs 运行日志)

部署失败排查时必须区分两类日志,不要只用 getDeployLog:

  1. 云端源码构建(传 targetPath、走 CODING 构建)
    • 先 queryCloudRun(action="getDeployLog", detailServerName=..., buildId=...) 查构建日志(编译/打包失败)
    • 再 queryCloudRun(action="getProcessLog", detailServerName=..., runId=...) 查运行日志(部署步骤 + 容器启动/健康检查)
  2. 已有镜像部署(传 imageUrl、DeployType=image)
    • 跳过 getDeployLog(无构建过程;且依赖 CODING,未登录会直接失败)
    • 直接 queryCloudRun(action="detail") 或 getDeployRecords 取 latestDeploy.RunId,再 getProcessLog 查运行日志
{
  "action": "getProcessLog",
  "detailServerName": "my-svc",
  "runId": "<from latestDeploy.RunId>"
}

Deploy-task SOP(撞到「已有部署发布任务运行中」时)

manageCloudRun(action="deploy") 报「已有部署发布任务运行中」/ already has a deploy task running 时,不要盲目重试,也不要反复改 Dockerfile / serverConfig —— 先确认任务真实状态:

  1. queryCloudRun(action="getManageTask", detailServerName=...) → 读 taskId / taskStatus / latestDeployStatus
  2. queryCloudRun(action="getProcessLog") → 隔 20–40 秒对比两次拉取,确认部署阶段步骤是否还在推进
  3. 按结果分支:
观察动作
taskStatus 仍是运行态,部署步骤有推进继续等,不要重发 deploy
任务已结束(非运行态),而 deploy 仍被拒才考虑重试
任务长时间停在非终态,版本也停在 creating 不动记录 taskId / latestDeployStatus / 时间窗作为证据,不要空转重试

force=true 不解决这个问题:它只跳过本工具的确认提示,不会取消或覆盖服务端已有的发布任务 —— 把它当「强制覆盖」用只会白撞一次。

日志侧的排查顺序(构建日志 vs 运行日志、先日志后配置)见上面的 Log query SOP 与 Container deploy failure SOP。

Write operations

  • manageCloudRun(action="initEnv") -> open (initialize) CloudRun for the environment — async, idempotent (Status=normal → already opened, no re-create). Use on a brand-new environment before the first deploy, or when deploy is blocked with an "尚未初始化云托管" message. Params: envId (defaults to the configured env), packageType (default Trial). Poll queryCloudRun(action="envStatus") until Status=normal.
  • manageCloudRun(action="init") -> create local project
  • manageCloudRun(action="download") -> pull remote code
  • manageCloudRun(action="run") -> local run for Function mode
  • manageCloudRun(action="deploy") -> trigger deploy + lightweight wait for registration (does not hang for full build; pass waitRegistration=false to skip even that wait when you don't need buildId). Returns buildId / runId / taskId + DeployType-aware next_step: source → getDeployLog then getProcessLog; image (imageUrl, BuildId often 0) → skip getDeployLog, use getDeployRecords/detail for RunId then getProcessLog. Follow the returned next_step — do not always poll build logs. Existing services: RMW preserves remote VpcConf / EnvParams keys / OpenAccessTypes; new services automatically validate that the environment's CloudRun is initialized — if not, deploy is blocked with guidance to call initEnv first
  • manageCloudRun(action="updateConfig") -> config-only update (no code upload; VPC / EnvParams / scaling / access types)
  • manageCloudRun(action="traffic") -> traffic management / canary release (aligns with tcb cloudrun traffic): trafficOp="set" adjusts the stable/canary traffic ratio (stablePercent + canaryPercent must equal 100, e.g. 90/10); trafficOp="promote" promotes the canary version to full release (100%, closes gray release, irreversible); trafficOp="rollback" rolls back to the previous stable version (stops the releasing canary). Check queryCloudRun(action="getDeployRecords") first to understand current versions and traffic
  • manageCloudRun(action="delete") -> delete service
  • manageCloudRun(action="createAgent") -> create Agent service

Deploying an existing image (imageUrl)

已有一个现成镜像(本地构建好、或第三方发布)时,不需要本地源码目录,直接 manageCloudRun(action="deploy") 传入 imageUrl 即可,走 DeployType="image"(容器型)部署,targetPath 可省略。若用户明确提到使用某个镜像或无需重新构建代码,必须传 imageUrl,不要仅因本地有源码目录就回退到源码构建。

决策路径(直填 vs 本地中转):

  1. 公网匿名可拉取(如 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 在节点上反复拉取失败,不要空转重试:改用 Dockerfile FROM <public-image> + targetPath 源码构建(CODING 拉公网镜像,产物进 CCR 内网拉取)。见下方 SOP 第 4 步。
  2. 私有 / 需登录的 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:latest
    
    然后把 ccr.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 或「常见默认值」猜。部署前必须确认:

  1. 启动命令 EntryPoint / Cmd(进程如何前台常驻)→ serverConfig.EntryPoint / Cmd
  2. 服务端口(进程真正 bind 的端口;不要假设 80/3000,也不要假设镜像尊重 PORT)→ serverConfig.Port
  3. 对外监听环境变量(必须 0.0.0.0 而不是 127.0.0.1、功能开关默认关闭等)→ EnvParams
  4. 数据目录挂载 → serverConfig.VolumesConf
  5. 健康端点(CloudRun readiness 探的是服务端口,不是任意 HTTP path)

缺任何一项再部署,失败看起来都会像「健康检查失败」。

2. 部署失败:用 getProcessLog 定性

镜像部署(imageUrl)跳过 getDeployLog(那是云端源码构建的构建日志)。从 detail / getDeployRecords 取 RunId,再 queryCloudRun(action="getProcessLog")。

启动日志存在 ≠ 服务正常运行。 banner、s6/tini 行、sidecar "listening" 都不能证明探针目标已起来。

两次日志对比判活: 隔 20–40 秒再拉一次 getProcessLog。

观察定性
只有调度/创建步骤(create_eks_*),没有容器 stdoutPod 调度中 / 镜像拉取
同一段启动 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 set serverConfig.VpcConf and use the database private address. Read references/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
  }
}

Deploy (existing app that connects to MySQL / PostgreSQL / Redis over 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:pass@10.x.x.x:5432/app\"}",
    "VpcConf": {
      "VpcId": "vpc-xxxxxxxx",
      "SubnetId": "subnet-xxxxxxxx"
    }
  }
}

Valid OpenAccessTypes values: OA (办公网访问), PUBLIC (公网访问), MINIAPP (小程序访问), VPC (VPC访问). Use PUBLIC for web applications that need public HTTPS access.

MinNum: 1 is the recommended default when you want to reduce cold-start latency. If the user explicitly prefers lower cost and accepts more cold starts, explain the tradeoff and let them reduce MinNum to 0.

Best practices

  1. Prefer PRIVATE/VPC or mini-program internal ingress when possible.
  2. For TCP database access, always pair private DB URLs with VpcConf in the same VPC/region as the database.
  3. Use environment variables for secrets and per-environment configuration — read them server-side only; never return them in HTTP responses. CloudBase API Keys come from manageAppAuth(action="createApiKey"), not from a local client login file.
  4. Verify configuration before and after deployment with queryCloudRun(action="detail").
  5. Keep startup work small to reduce cold-start impact.
  6. For Agent scenarios, use the Agent SDK skill for protocol and adapter details instead of duplicating them here.
  7. For smoke tests, return a fixed { "ok": true } / health payload — never deploy httpbin or any service that reflects request headers.

Troubleshooting hints

  • Access failure -> check ingress access type, domain setup, and whether the instance scaled to zero.
  • Deployment blocked with "尚未初始化云托管 / not initialized" -> the environment needs CloudRun enabled first: call manageCloudRun(action="initEnv", envId=...) (异步开通) and poll queryCloudRun(action="envStatus") until Status=normal; or open the console 环境 → 云托管 → 开通. For stateless HTTP services, consider an HTTP cloud function instead of CloudRun entirely.
  • Deployment failure -> follow the Container deploy failure SOP above (and references/image-deploy-troubleshooting.md): image deploys skip getDeployLog and use getProcessLog only; classify scheduling vs port vs exit-on-start with two log pulls. Do not raise InitialDelaySeconds until logs prove a single slow init. Also inspect Dockerfile (source) and CPU/memory ratio.
  • Deploy rejected with "a deploy task is already running" / 「已有部署发布任务运行中」 -> read the real task state with queryCloudRun(action="getManageTask") first. Do not retry blindly, and do not set force=true expecting an override — it only skips this tool's confirmation prompt. See the Deploy-task SOP above.
  • Deploy accepted but the version never leaves creating -> queryCloudRun(action="getManageTask") for latestDeployStatus + taskStatus, then getProcessLog for the deploy-phase steps. Only change Dockerfile / serverConfig once the logs actually point at code or config.
  • Local run failure -> remember only Function mode is supported by local-run tools.
  • Performance issues -> reduce dependencies, optimize initialization, and tune minimum instances.
  • DB / Redis connection failure after a successful deploy -> almost always missing or wrong VpcConf, wrong private host, or security group. Follow references/vpc-and-database.md before rewriting application code.
  • CloudBase SDK call fails inside the service with missing / invalid credentials -> the credential gate above was skipped, or the variable name is not the official one. Issue a key with manageAppAuth(action="createApiKey"), inject it as CLOUDBASE_APIKEY through EnvParams, redeploy, then verify a real read. See ../cloud-functions/references/http-function-credentials.md.

Reference index

All packaged reference files (required for skill lint reachability):

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

skills/cloudrun-development

Default branch

main

Latest commit

c97a456

Tree SHA

5ae6ac6