Skip to main content

Tutorial: Deploy the Sample Project

Use the CLI to deploy Cloud Functions, Static Hosting, gateway, and CloudBase Run to one environment, and then run one cloud build deployment through the Cloud API. All steps were verified on CloudBase CLI 3.8.5.

This tutorial is for first-time deployments. Follow it to get a working result. For the full list of options and parameters, see CLI and Cloud API Deployment Reference. To create a pipeline in the console, see Create and Manage Pipelines in the Console.

Prerequisites​

ItemRequirement
Node.js18 or later
CloudBase CLInpm i -g @cloudbase/cli. tcb -v prints a version
CloudBase environmentAn available environment. Note its environment ID. Run tcb env list to view it
LoginRun tcb login and complete the authorization

⚠️ The steps below create and overwrite resources in the environment. Use a test environment.

<envId> below stands for the environment ID.

Sample project​

The project contains four kinds of resources:

deploy-demo/
├── cloudbaserc.json # Declares Cloud Functions, Static Hosting, gateway
├── functions/
│ └── demo-fn/
│ ├── index.js
│ └── package.json
├── web/ # Frontend project
│ ├── index.html
│ ├── package.json
│ ├── vite.config.js
│ └── src/main.js
└── cloudrun/
└── demo-run/ # CloudBase Run service
├── Dockerfile
├── package.json
└── server.js

tcb config init can interactively generate cloudbaserc.json and a minimal skeleton under functions/ and web/, but the result cannot be used as is for this tutorial. The function has no package.json, so calling it after deployment fails with 0 code exit unexpected. The deployPath of Static Hosting defaults to /, which overwrites the site at the environment root. This tutorial uses the complete files below.

Cloud Function​

functions/demo-fn/index.js:

exports.main = async () => ({
statusCode: 200,
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: JSON.stringify({ message: 'hello from cloud function', version: 'v1' })
})

functions/demo-fn/package.json:

{ "name": "demo-fn", "version": "1.0.0", "main": "index.js" }

Frontend project​

web/package.json:

{
"name": "demo-web",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": { "build": "vite build" },
"devDependencies": { "vite": "^5.4.0" }
}

web/vite.config.js:

import { defineConfig } from 'vite'

export default defineConfig({ base: './' })

base: './' makes the build use relative asset paths. When the page is deployed under a subpath such as /demo, omitting this line makes requests for /assets/* return 404.

web/index.html:

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Deploy Demo</title>
</head>
<body>
<h1 id="title">Deploy Demo v1</h1>
<script type="module" src="./src/main.js"></script>
</body>
</html>

web/src/main.js:

console.log('deploy demo v1')

CloudBase Run service​

cloudrun/demo-run/server.js:

const http = require('http')

http
.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' })
res.end(JSON.stringify({ message: 'hello from cloudrun', version: 'v1' }))
})
.listen(process.env.PORT || 3000)

cloudrun/demo-run/package.json:

{ "name": "demo-run", "version": "1.0.0", "main": "server.js" }

cloudrun/demo-run/Dockerfile:

FROM node:18-alpine
WORKDIR /app
COPY package.json server.js ./
EXPOSE 3000
CMD ["node", "server.js"]

Configuration file​

cloudbaserc.json. Replace envId with your environment ID:

{
"version": "2.1",
"envId": "<envId>",
"functionRoot": "./functions",
"functions": [
{
"name": "demo-fn",
"type": "Event",
"runtime": "Nodejs18.15",
"handler": "index.main",
"timeout": 10
}
],
"hosting": [
{
"name": "web",
"root": "./web",
"framework": "vite",
"installCommand": "npm install",
"buildCommand": "npm run build",
"outputDir": "dist",
"deployPath": "/demo"
}
],
"gateway": {
"routes": [
{ "path": "/demo-api", "target": "function:demo-fn" },
{ "path": "/demo", "target": "hosting:web" }
]
}
}

For field descriptions, see Configuration file. CloudBase Run is not in this file. It is deployed separately. See Deploy CloudBase Run.

Deploy Cloud Functions, Static Hosting, and gateway​

1. Validate the configuration​

tcb validate

The output shows [PASS] and a resource overview: 1 Cloud Function, 1 Static Hosting site, and 2 gateway routes. When deployPath is a subpath, a warning about the frontend base appears. You can ignore it because base: './' is already set.

2. Install dependencies and build​

npm install --prefix web
tcb app build

tcb app build only builds and does not install dependencies. Install them in the web/ directory. Running npm install in the project root makes the build fail with "node_modules not detected".

After a successful build, the artifacts are in web/dist/.

3. Preview changes​

tcb deploy --dry-run

The plan of the first deployment has 4 steps, all new:

[1/4] Cloud Function (demo-fn) Create
[2/4] Static Hosting (web) Direct upload
[3/4] Gateway (/demo-api) Create
[4/4] Gateway (/demo) Create

4. Deploy​

tcb deploy --yes

On success, the command prints the access URL of each resource and exits with code 0:

✔ Deployment complete: 4 resources succeeded
✔ Cloud Function demo-fn
✔ Static Hosting web
URL: https://<envId>-<appId>.tcloudbaseapp.com/demo/
✔ Gateway /demo-api
URL: https://<envId>-<appId>.ap-shanghai.app.tcloudbase.com/demo-api
✔ Gateway /demo
URL: https://<envId>-<appId>.ap-shanghai.app.tcloudbase.com/demo/

The CLI output is in Chinese. The block above is translated for readability.

5. Verify​

Use the gateway URLs from the output:

curl https://<envId>-<appId>.ap-shanghai.app.tcloudbase.com/demo-api
# {"message":"hello from cloud function","version":"v1"}

curl https://<envId>-<appId>.ap-shanghai.app.tcloudbase.com/demo/
# Returns the page, which contains <h1 id="title">Deploy Demo v1</h1>

View the resources in the console:

ResourceLocation
Cloud FunctionCloud Functions list
Static siteStatic Hosting → File Management → demo directory
Gateway routesHTTP Access Service

The static site does not appear in the Apps list. For the reason, see Two deployment forms of Static Hosting.

6. Redeploy after changes​

Change v1 to v2 in functions/demo-fn/index.js and web/index.html, then rebuild and deploy:

tcb app build
tcb deploy --yes

The summary shows the Cloud Function as "overwrite update", and the two gateway routes, whose configuration is unchanged, as "skipped". After the deployment, the Cloud Function returns v2 and the page title is Deploy Demo v2.

⚠️ If you skip tcb app build, tcb deploy uploads the previous artifacts in web/dist, and the page stays at v1. The command does not fail. It only prints a notice that existing build artifacts were detected and the local build was skipped.

Deploy CloudBase Run​

tcb cloudrun deploy -s demo-run --source ./cloudrun/demo-run --port 3000 --force --yes --wait
OptionDescription
-sService name. Created automatically if it does not exist
--sourceCode directory, which must contain a Dockerfile
--portContainer listening port
--force --yesSkip confirmation
--waitBlocks until the deployment finishes. Exits with code 0 on success

When the command ends, it prints a success message. For all parameters, see Code deployment.

Query the access URL:

tcb cloudrun detail -s demo-run -e <envId>

DefaultDomainName in the JSON output is the default access URL. Its format is like https://demo-run-<number>-<appId>.sh.run.tcloudbase.com. Use the value from the command output:

curl <DefaultDomainName>/
# {"message":"hello from cloudrun","version":"v1"}

After you change the code, run the same command again. The service generates a new deployment record:

tcb cloudrun record list -s demo-run -e <envId>

A new version has the status creating. It receives requests after the status becomes normal and its traffic ratio is 100. For a few seconds after the switch, you may still reach the old version.

Deploy as an app​

For a frontend project with a build step, use tcb app deploy to build in the cloud. The result is an app in the Apps list, with its own domain and version records.

cd web
tcb app deploy demo-app \
--framework vite \
--install-command "npm install" \
--build-command "npm run build" \
--output-dir dist \
--deploy-path /demo-app \
--ignore "node_modules,dist" \
--force -e <envId>

Run it inside the web/ directory. If you point to the subdirectory from the project root with --cwd ./web or app.root, the cloud build fails at the install step. See Cloud build deployment.

After a successful deployment, the access URL is printed:

✔ Deployment succeeded!
URL: https://demo-app-<envId>.webapps.tcloudbase.com/
Version: demo-app-001

After the first successful deployment, the CLI writes a cloudbaserc.json into web/. It duplicates the one in the project root. Delete it when needed to avoid confusion.

When a build fails, view the log to locate the cause:

tcb app versions list demo-app -e <envId>
tcb api tcb DescribeCloudBaseRunBuildLog --api-version 2018-06-08 \
--body '{"EnvId":"<envId>","ServiceName":"demo-app","ServiceVersion":"demo-app-001","BuildId":<BuildId>,"Start":0}'

Get BuildId from the output of tcb app versions list.

Deploy through Cloud API​

Use the Cloud API to hand a code archive to a cloud build, which suits self-built platforms. The commands below use tcb api, which handles signing. For signing in your own calls, see Common request parameters.

1. Package the code​

cd web
zip -qr /tmp/demo-web.zip . -x "node_modules/*" "dist/*"

The archive root contains the project files directly, including package.json.

2. Get the upload URL​

tcb api tcb DescribeCloudAppCosInfo --api-version 2018-06-08 --json \
--body '{"EnvId":"<envId>","ServiceName":"demo-api-app","DeployType":"custom","Suffix":".zip"}'

UploadUrl in the response is the signed upload URL. UnixTimestamp is used in the next steps. When UploadHeaders is an empty array, the upload request needs no extra headers.

3. Upload the archive​

curl -X PUT --upload-file /tmp/demo-web.zip "<UploadUrl>"

A successful upload returns HTTP 200.

4. Create the build​

tcb api tcb CreateCloudApp --api-version 2018-06-08 --json --body '{
"EnvId": "<envId>",
"ServiceName": "demo-api-app",
"DeployType": "custom",
"Source": {
"Type": "zip",
"CosTimestamp": "<UnixTimestamp>",
"CosSuffix": ".zip",
"PackageFileName": "package.zip"
},
"Commands": {
"InstallCmd": "npm install",
"BuildCmd": "npm run build",
"DeployCmd": "tcb hosting deploy dist /demo-api-app -e <envId>"
},
"NodeJsVersion": "20"
}'

The response returns BuildId and VersionName, such as demo-api-app-001.

⚠️ Do not omit -e <envId> in DeployCmd. The CLI in the build environment is logged in but has no default environment. Without this option, the deploy step fails with No valid environment ID was detected.

5. Query the build status​

tcb api tcb DescribeCloudAppVersion --api-version 2018-06-08 --json \
--body '{"EnvId":"<envId>","ServiceName":"demo-api-app","DeployType":"custom","VersionName":"demo-api-app-001"}'

Status goes from BUILDING to SUCCESS or FAILED, and Steps lists the status of each step. Query every 10 seconds. The sample project finishes within about 10 seconds.

On success, Steps is:

Checkout ZIP → install → build → deploy → End, all success

6. Verify​

When DeployType is custom, artifacts are deployed to a Static Hosting file directory. The access URL is:

https://<envId>-<appId>.tcloudbaseapp.com/demo-api-app/

This deployment does not appear in the console Apps list. To make it appear there, use Deploy as an app.

7. View the build log​

When a build fails, query the log with BuildId:

tcb api tcb DescribeCloudBaseRunBuildLog --api-version 2018-06-08 --json \
--body '{"EnvId":"<envId>","ServiceName":"demo-api-app","ServiceVersion":"demo-api-app-001","BuildId":<BuildId>,"Start":0}'

The log is in Log.Text of the response, split by step. For parameter details, see CLI and Cloud API Deployment Reference.

Comparison​

MethodResourceBuild locationForm in the cloud
tcb deployCloud Functions, Static Hosting, gatewayLocal, run tcb app build firstStatic file directory, no app entity
tcb cloudrun deployCloudBase RunCloudCloudBase Run service with deployment records
tcb app deployFrontend appCloudApp with versions and its own domain
Cloud API CreateCloudAppFrontend projectCloudStatic file directory (custom)

FAQ​

tcb app build reports "node_modules not detected"​

Dependencies are not installed in the hosting[].root directory. Run npm install --prefix web.

The page is still the old version after deployment​

tcb deploy does not build. It uploads the existing outputDir. Run tcb app build first.

Blank page, /assets/* returns 404​

The frontend build uses absolute asset paths, but the page is deployed under a subpath. For a Vite project, set base: './'.

Cloud build fails with cd: can't cd to /root/cloudbase-workspace/./web​

You pointed to a subdirectory from the project root with --cwd or app.root. Enter the subdirectory and run tcb app deploy.

The Cloud API deploy step reports No valid environment ID was detected​

The CLI command in DeployCmd lacks -e <envId>.

The app is not in the Apps list after deployment​

hosting in tcb deploy and the custom type of the Cloud API deploy to a Static Hosting file directory, not to an app. View it in Static Hosting → File Management, or use tcb app deploy.