Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

how to use Cloud Builder for NodeJS application - Virtual Machine

I am trying from last two days and not a big success yet, I am not sure if I am on right path: Here is my scenario:

Created a VM in google cloud compute engine and enabled http & https
Enabled CLOUD BUILDER API and created trigger for GitHub push in main branch
Also enabled the compute instance admin v1 (compute engine) inside settings -> Service account permissions
So I am developing an sample test NodeJS app to check how to automate everything from push to live deployment and I can see examples and guide for push and deployment via cloud run , app engine, GKE etc. but didn't find any guide for deploying to compute engine virtual machine;

here are some of files how I am trying to deploy my NodeJS application

index.js

const express = require('express');
const app = express()
const port=3000;

app.get('/',(req,res)=>{
    res.send('Hello World')
});

app.listen(port,()=>{
    console.log('sample app is running on port ${port}')
})

------------------------------------------------------

Dockerfile

FROM node:16

RUN mkdir -p /usr/src/app

# Create app directory
WORKDIR /usr/src/app


COPY package.json /usr/src/app/

RUN npm install


# Bundle app source
COPY . /usr/src/app

EXPOSE 3000
CMD [ "npm", "start" ]

--------------------------------------------------

cloudbuild.yaml

steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build','-t', 'eu.gcr.io/mysample-app/sampletestapp:latest','.']
   
    - name: 'gcr.io/cloud-builders/docker'
      args: ['push','eu.gcr.io/mysample-app/sampletestapp:latest',]
   
    - name: 'gcr.io/cloud-builders/docker'
      args: ['run','--publish', '3000:3000','eu.gcr.io/mysample-app/sampletestapp:latest']
   
    images: ['eu.gcr.io/mysample-app/sampletestapp:latest']

-----------------------------------------------------------

With all above setup when I commit some changes, i can see trigger is running and it build the application successfully, and it fails at docker run 
 
 
Finished Step #1
Starting Step #2
Step #2: Already have image (with digest): gcr.io/cloud-builders/docker
Step #2: 
Step #2: > testapp@1.0.0 start
Step #2: > dist/index.js
Step #2: 
Step #2: sh: 1: dist/index.js: Permission denied
Finished Step #2
ERROR
ERROR: build step 2 "gcr.io/cloud-builders/docker" failed: step exited with non-zero status: 126




But even after successfully build I am unable to access my API (which is simple / root) Also when login to VM via SSH I don't see anything on that WORKDIR (/usr/src/app) /app directory doesn't exist, also found that docker is not installed

So I need help in these :

How cloud builder know where to build and deploy because I didn't mentioned any linking with my virtual machine in cloudbuilder.yml, which VM it will use to deploy or if we don't mention then it choose the first running VM
Is it possible to build and run automatically on VM via this approach ?, if not what I can do?
Is something wrong in my code ?
sorry for my bad explanation, Any help would be much appreciated

Thanks
0 1 887
1 REPLY 1

glen_yu
Google Developer Expert
Google Developer Expert

Typically, you would deploy to a service like Cloud Run, AppEngine or GKE.   However, (standalone via gcloud) you can start a new GCE/VM and have it run a docker image.

Normally, if you were to do this via a gcloud command, it would look something like:

gcloud compute instances create-with-container [VM_NAME] \
  --container-image gcr.io/[PROJECT_ID]/[IMAGE_NAME]:[IMAGE_TAG]

The doc is here but if memory serves, you won't have to specify any port mappings as it runs with --net=host essentially, so the only thing you will need to do is make sure you have a firewall rule to allow ingress on port 3000

 

As for the reason why your 3rd step (step #2) doesn't work, is because those are NOT local commands run from the machine your container is to be deployed on.  These are commands run on ephemeral containers which has the your required binary (i.e. docker or gcloud).  Think of those command as being run from your laptop or desktop: so running docker run -p 3000:3000 myimage:mytag would only run the image locally on your laptop, but it wouldn't run it it on your target GCE/VM.

 

For your 3rd step (step #2), I think you'd need something like:

 

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args:
  - 'compute'
  - 'instances'
  - 'create-with-container'
  - etc.
  - etc.


DISCLAIMER: I've never tried this so I don't know if this will actually work as Cloud Build is not meant to do this, although in theory it should as long as it has the right permissions when running the gcloud command...which brings me to my next point, which is the default Cloud Build service account wouldn't have permissions to run gcloud compute commands, so you'll either have to add Compute Instance Admin (v1) role to it or point it to use another service account that does have the correct perms.