An Express app as a web service in Cloud Run

Let's say you have an idea for a Node app.

You make a new folder, run npm init -y, then npm install express to get started.

Create app.js and add the app with an endpoint:

const express = require('express')

module.exports = express.get('/', (req, res) => {
  res.send('Hello World!')

Create index.js then run node . to start the service:

const app = require('./app')

app.listen(process.env.PORT, () => {
  console.log(`Listening on port ${process.env.PORT}`)

Now turn it into a public web service, by packaging the app in a Docker container that can be deployed anywhere.

Create a Dockerfile to describe the build process for a Docker image:

FROM node:12-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . ./
CMD ["node", "."]

Test the containerized service locally, by creating a description of the service in docker-compose.yml and running docker-compose up, then opening http://localhost:8080/:

version: '3'
    build: .
      PORT: 8080
      - 8080:8080

Next, create a new project in the Google Cloud Platform console. Edit the project id if you like, perhaps replacing the random numeric suffix with the current year, as a reminder of when it was created.

Install the Google Cloud SDK, if you need to.

Send Dockerfile and the local context to Cloud Build, so it can build a Docker image:

gcloud builds submit --tag$PROJECT/$IMAGE

Finally, deploy the image to Cloud Run, as a new service:

gcloud run deploy $SERVICE --image$PROJECT/$IMAGE --platform managed --allow-unauthenticated --region $REGION

If you need to set any environment variables, it's easiest to do that in the Cloud Run console, under "Edit and deploy new revision".

You can assign a subdomain to the service by choosing "Manage custom domains" then "Add mapping" in the Cloud Run console and adding a CNAME in your domain registrar pointing to the address it gives you.