iTranslated by AI
Quickly Deploying an Express (Node.js) + TypeScript Environment to Cloud Run
Introduction
I always forget this, so I'm writing it down for future reference.
In this article, we aim to deploy an Express (Node.js) + TypeScript project to Cloud Run.
Prerequisites
- An environment where the
gcloudcommand-line tool is enabled - Executed on zsh on Mac (It should work in WSL2 or Linux environments, but please adapt the commands accordingly if things don't go well in other environments)
- Installation of Node.js and npm (preferably the latest LTS version if possible)
Creating the Express (Node.js) + TypeScript project
Create a project directory and initialize it with npm (you can mostly just press Enter for the input prompts).
❯ mkdir express-ts
❯ cd express-ts
❯ npm init
Install the necessary modules via npm.
❯ npm install typescript @types/node ts-node-dev express @types/express npm-run-all
Create tsconfig.json.
❯ npx tsc --init
Rewrite the contents of tsconfig.json as you like.
The following is an example.
- Place TypeScript source code under the
srcdirectory - Place transpiled JavaScript files under the
distdirectory
This is the configuration. Other TypeScript options have also been changed.
{
"compilerOptions": {
"allowJs": true,
"target": "ES2020",
"module": "commonjs",
"sourceMap": true,
"outDir": "./dist",
"strict": true,
"strictNullChecks": true,
"alwaysStrict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
Create the src directory under the express-ts directory and create the app.ts file.
import express, { Application, Request, Response } from "express";
const app: Application = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/", async (req: Request, res: Response) => {
return res.status(200).send({
message: "Hello World!",
});
});
const port = process.env.PORT || 8000;
try {
app.listen(port, () => {
console.log(`Running at Port ${port}...`);
});
} catch (e) {
if (e instanceof Error) {
console.error(e.message);
}
}
Rewrite the main and scripts in package.json as follows:
"main": "dist/app.js",
"scripts": {
"start": "node .",
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "ts-node-dev --respawn src/app.ts",
"clean": "rimraf dist",
"tsc": "tsc",
"build": "npm-run-all clean tsc"
},
Start Express with the following command.
❯ npm run dev
> express-ts@1.0.0 dev
> ts-node-dev --respawn src/app.ts
[INFO] 12:28:44 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.1, typescript ver. 4.9.4)
Running at Port 8000...
Once the string "Running at Port 8000..." appears as shown above, access the following URL to confirm the server starts correctly:
http://localhost:8000/

Also, since the ts-node-dev package is used internally, it supports real-time source code updates (hot reload), which improves development efficiency. For example, if you change the string "Hello World!" and refresh your browser, the response string will change.
Cloud Run Settings
Create a new project on GCP and set the project ID using the following command. Manually replace [PROJECT_ID] with your GCP project ID and execute the command.
export PROJECT_ID=[PROJECT_ID]
To run Cloud Run, ensure that billing is enabled for the project in GCP.
❯ gcloud beta billing projects describe ${PROJECT_ID} | grep billingEnabled
billingEnabled: true
Switch the target project for the gcloud command to the new project.
❯ gcloud config set project ${PROJECT_ID}
Updated property [core/project].
Set the default region and platform for Cloud Run.
gcloud config set run/region asia-northeast1
gcloud config set run/platform managed
Placing the Dockerfile
Place a Dockerfile with the following content in the project directory.
FROM node:lts-slim
WORKDIR /usr/src/app
ENV PORT 8080
COPY package*.json ./
RUN npm install --only=production
COPY . ./
RUN npm run build
CMD [ "npm", "start" ]
Deployment
The deployment method to Cloud Run is extremely simple.
It can be done with a single gcloud run deploy command.
If you are asked anything, please read the content.
- Note: Since this is for verification, you should be able to proceed mostly with Enter and "y" if prompted.
❯ gcloud run deploy --source .
Service name (express-ts):
API [artifactregistry.googleapis.com] not enabled on project [1234567890]. Would you like to enable and retry (this will take a few minutes)?
(y/N)? y
Enabling service [artifactregistry.googleapis.com] on project [1234567890]...
Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in
region [asia-northeast1] will be created.
Do you want to continue (Y/n)? y
This command is equivalent to running `gcloud builds submit --tag [IMAGE] .` and `gcloud run deploy express-ts --image [IMAGE]`
API [run.googleapis.com] not enabled on project [1234567890]. Would you like to enable and retry (this will take a few minutes)? (y/N)? y
Enabling service [run.googleapis.com] on project [1234567890]...
Allow unauthenticated invocations to [express-ts] (y/N)? y
Building using Dockerfile and deploying container to Cloud Run service [express-ts] in project [express-ts-123456] region [asia-northeast1]
⠧ Building and deploying new service... Uploading sources.
⠼ Building and deploying new service... Uploading sources.
✓ Uploading sources...
. Building Container...
⠏ Building and deploying new service... Uploading sources.
⠹ Building and deploying new service... Uploading sources.
X Building and deploying new service... Uploading sources.
API [cloudbuild.googleapis.com] not enabled on project [1234567890]. Would you like to enable and retry (this will take a few minutes)? (y/N)?
y
Enabling service [cloudbuild.googleapis.com] on project [1234567890]...
Deployment failed
ERROR: (gcloud.run.deploy) INVALID_ARGUMENT: could not resolve source: googleapi: Error 403: 1234567890@cloudbuild.gserviceaccount.com does not have storage.objects.get access to the Google Cloud Storage object. Permission 'storage.objects.get' denied on resource (or it may not exist)., forbidden
An error message will be displayed once as shown above. As indicated by Permission 'storage.objects.get' denied on resource (or it may not exist)., forbidden, this is a permissions issue.
If you selected "y" for API [cloudbuild.googleapis.com] not enabled on project [1234567890]. Would you like to enable and retry (this will take a few minutes)?, the permissions should now be enabled.
Don't panic, and run the following command again.
❯ gcloud run deploy --source .
Service name (express-ts):
This command is equivalent to running `gcloud builds submit --tag [IMAGE] .` and `gcloud run deploy express-ts --image [IMAGE]`
Allow unauthenticated invocations to [express-ts] (y/N)? y
Building using Dockerfile and deploying container to Cloud Run service [express-ts] in project [express-ts-123456] region [asia-northeast1]
⠶ Building and deploying new service... Deploying Revision. Waiting on revision express-ts-00001-pag.
✓ Uploading sources...
✓ Building and deploying new service... Done.
⠶ Creating Revision... Revision deployment finished. Checking container health.
. Routing traffic...
✓ Setting IAM Policy...
✓ Creating Revision... Revision deployment finished. Checking container health.
✓ Routing traffic...
Enabling service [run.googleapis.com] on project [1234567890]...
Done.
Service [express-ts] revision [express-ts-00001-pag] has been deployed and is serving 100 percent of traffic.
Service URL: https://express-ts-qwerty-an.a.run.app
Access the issued Service URL and confirm that the response is the same as the previous localhost result.
If you want to edit Cloud Run environment variables, memory, etc., go to the console at the URL below, select the service name (express-ts) > "Edit and Deploy New Revision" to configure the settings.
https://console.cloud.google.com/run
Great job!
Cleanup
Delete the project when it is no longer needed to avoid incurring costs.
- Delete the Google Cloud default project setting
gcloud config unset project - Delete the project
gcloud projects delete ${PROJECT_ID} - Delete the hands-on materials
Delete theexpress-tsdirectory
References
gcp-getting-started-cloudrun/tutorial.md at main · google-cloud-japan/gcp-getting-started-cloudrun
Setting up an environment for Express and TypeScript
Note: The official Google Cloud Japan reference is particularly helpful as it describes the internal behavior of Cloud Run. If you want to learn more, please take a look when you have time.
Discussion
감사합니다 !!!
ありがとうごじゃいます!!