I have a vanilla nestjs monorepo that I am failing to run on Google App Engine. We first have to deploy a default service on GAE which I have attempted to do by taking the default nest app (my-app) in the monorepo and adding my app.yaml config and also a cloudbuild.json config file. The project looks like this:
apps
my-app
src
app.controller.ts
app.module.ts
app.service.ts
main.ts
tsconfig.app.json
app.yaml // GCP config file
clouldbuild.json // GCP config file
my-project
src
app.controller.ts
app.module.ts
app.service.ts
main.ts
tsconfig.app.json
nest-cli.json
package.json
tsconfig.json
node_modules
The error I get is when I deploy to GAE is :
no such file or directory, open '/workspace/package.json'
I guess this is because the package.json is not at the same level as app.yaml. However as this is a monorepo and the package.json is shared across apps how should I configure GAE and Cloud Build to read the package.json from the root folder but only deploy the service in app.yaml? The app.yaml according to gcp docs the app.yaml has to be at the same level as the source files. GCP docs link
This solution assumes the below structure of NestJs Monorepo (also of OP's), which is the default monorepo structure created using NestJs nest generate app my-app command.
|-root
| |-apps
| | |-nest-app-1
| | |-nest-app-2
|-nest-cli.json
|-package.json
As per GCP Doc Running a custom build step
Modify the script tag in the package.json file. Add gcp-build under scripts and chain the build of all your apps. Like below:
"gcp-build": "nest build nest-app-1 && nest build nest-app-2"
Alternatively, you can also modify it like below should you need to build individual projects later.
"build:nest-app-1": "nest build nest-app-1", <-- build app 1
"build:nest-app-2": "nest build nest-app-2", <-- build app 2
"gcp-build": "yarn run build:nest-app-1 && yarn run build:nest-app-2", <-- chain the builds
In the root of your project (next to package.json), create two files. One for each app.
|-root
| |-apps
| | |-nest-app-1
| | |-nest-app-2
|-nest-cli.json
|-package.json
|-gcp.nest-app-1.yaml <-- config file for nest-app-1
|-gcp.nest-app-2.yaml <-- config file for nest-app-2
We need to mainly define these 3 property:
main.js. You can look for entryFile under nest-cli.json file or build the project locally look into the dist folder manually.Below is how the config files should look now (select your node version):
File gcp.nest-app-1.yaml
runtime: nodejs18
service: nest-app-1
entrypoint: node dist/apps/nest-app-1/main
env_variables:
PORT: "8080"
File gcp.nest-app-2.yaml
runtime: nodejs18
service: nest-app-2
entrypoint: node dist/apps/nest-app-2/main
env_variables:
PORT: "8080"
Tip: use --no-cache during testing to avoid picking existing layers.
gcloud app deploy gcp.nest-app-1.yaml --no-cache
gcloud app deploy gcp.nest-app-2.yaml --no-cache
This should get your NestJs monorepo application up in the cloud in no time.
Side Tip: You can then take advantage of dispatch.yaml to further route the calls based on the URL. More Structuring web services in App Engine
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With