loading...

NestJS + Cloud Run With Authentication - Bare Bones

amammay profile image Alex Mammay ・3 min read

IMO NestJS has been a blast to play with, and really has let me build out rapid prototypes, while forcing me to keep a domain driven design and value unit testing up front.
I plan to use this article a baseline to reference for other nestjs articles that i will be building out over the next couple of weeks.

pre reqs

  • gcloud cli installed --> here
  • NestJs cli installed globally --> here

Generate nest js project

  1. generate nestjs project ( we will name ours cloud-run )

    • nest new cloud-run
  2. update nestjs to respect port environment variable

src/main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Logger } from '@nestjs/common';

const logger = new Logger('APP');
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const port = process.env.PORT || 3000;
  await app.listen(port, () => {
    logger.log(`⛱ server running on port ${port}`)
  });
}
bootstrap();

invoke npm run start:dev to see the app start up
invoke npm run test:cov to see the unit test run and that sweet 100% code coverage

-------------------|----------|----------|----------|----------|-------------------|
File               |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files          |      100 |      100 |      100 |      100 |                   |
 app.controller.ts |      100 |      100 |      100 |      100 |                   |
 app.service.ts    |      100 |      100 |      100 |      100 |                   |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.451s
Ran all test suites.


invoke npm run test:e2e to see the e2e suite run

Cloud build

Now let us do some configuration to get this to run on cloud build

We will create the following files

  1. Dockerfile
# use node 10 image
FROM node:10 as base

# set our working directory
WORKDIR /app

FROM base as development

# copy over dependecy manifests to install
COPY package*.json ./

# install production dependencies and copy them to a temp folder, we will use this for the final build step
RUN npm install --production
RUN cp -R node_modules /tmp/node_modules

# Install all dependcies
RUN npm install

# Copy source code
COPY . ./

# lint, unit test, e2e test and build our app
FROM development as builder
RUN npm run lint
RUN npm run test:cov
RUN npm run test:e2e
RUN npm run build

# release includes bare miniumum to run the app
FROM base as release
COPY --from=builder /tmp/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./

# Run the web service on container boot
CMD ["npm", "run", "start:prod"]

  1. .dockerignore
coverage
node_modules/
dist
.idea
.vscode

  1. cloudbuild.yaml
steps:
  # build the container image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/$_SERVICE_NAME', '.']
  # push the container image to Container Registry
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/$_SERVICE_NAME']
  # Deploy container image to Cloud Run
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - 'run'
      - 'deploy'
      - 'cloud-run'
      - '--image'
      - 'gcr.io/$PROJECT_ID/$_SERVICE_NAME'
      - '--region'
      - '$_REGION'
      - '--platform'
      - 'managed'
      - '--no-allow-unauthenticated'
images:
  - 'gcr.io/$PROJECT_ID/$_SERVICE_NAME'
substitutions:
  _SERVICE_NAME: "cloud-run"
  _REGION: "us-central1"

Service account adjustment

  1. Log into gcp and go to cloud build settings and give the cloud build service account Cloud Run Admin and Service Account User

Service Account

Trigger build

from you command line type gcloud builds submit and watch the build and auto deployment

Test it out!

curl -H \
"Authorization: Bearer $(gcloud auth print-identity-token)" \
$(gcloud run services describe SERVICENAME --format 'value(status.url)')

Discussion

markdown guide