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
| Item | Requirement |
|---|---|
| Node.js | 18 or later |
| CloudBase CLI | npm i -g @cloudbase/cli. tcb -v prints a version |
| CloudBase environment | An available environment. Note its environment ID. Run tcb env list to view it |
| Login | Run 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 initcan interactively generatecloudbaserc.jsonand a minimal skeleton underfunctions/andweb/, but the result cannot be used as is for this tutorial. The function has nopackage.json, so calling it after deployment fails with0 code exit unexpected. ThedeployPathof 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:
| Resource | Location |
|---|---|
| Cloud Function | Cloud Functions list |
| Static site | Static Hosting → File Management → demo directory |
| Gateway routes | HTTP 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 deployuploads the previous artifacts inweb/dist, and the page stays atv1. 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
| Option | Description |
|---|---|
-s | Service name. Created automatically if it does not exist |
--source | Code directory, which must contain a Dockerfile |
--port | Container listening port |
--force --yes | Skip confirmation |
--wait | Blocks 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>inDeployCmd. The CLI in the build environment is logged in but has no default environment. Without this option, the deploy step fails withNo 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
| Method | Resource | Build location | Form in the cloud |
|---|---|---|---|
tcb deploy | Cloud Functions, Static Hosting, gateway | Local, run tcb app build first | Static file directory, no app entity |
tcb cloudrun deploy | CloudBase Run | Cloud | CloudBase Run service with deployment records |
tcb app deploy | Frontend app | Cloud | App with versions and its own domain |
Cloud API CreateCloudApp | Frontend project | Cloud | Static 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.