node.jsgoogle-cloud-platformcontainersgoogle-cloud-run

How to include local dependencies in Node.js Google Cloud Run service


I am trying to turn a function in my project repo into a Cloud Run service. In my file, I include some local dependencies using require statements. I followed the quickstart instructions on Google Run, and in my package.json I included these dependencies using the file indicator. I've included the dependencies portion of my package.json below:

  "dependencies": {
    "express": "^4.17.1",
    "embeddings": "file:../../embeddings.js",
    "opt": "file:../../opt.js",
    "gpt": "file:../../gpt.js",
    "pinecone": "file:../../pinecone.js",
    "users": "file:../../users.js"
  }

When I try to deploy the service with gcloud run deploy, I run into a 'MODULE_NOT_FOUND' error. I can't find any info online about how to properly configure this.


Solution

  • I'm not a Node.js developer but familiar with Cloud Run.

    I suspect your issue is that gcloud run deploy attempts to build a container for your project (using a buildpack) but is unable to access references outside the context (of your current project; in the current folder).

    You've choices:

    1. Containerize the app yourself
    2. Private registry
    3. Vendor
    4. Manually configure node_modules to include the dependencies
    Vendor

    Example:

    .
    ├── a
    │   ├── index.js
    │   └── package.json
    └── b
        ├── index.js
        └── package.json
    

    Where b has a dependency on a and b's package.json includes:

    {
      "name": "b",
      "dependencies": {
        "a": "file:../a"
      }
    }
    

    NOTE The package is outside (..) of the context.

    This will fail.

    To vendor a, move it under a(ny) designated folder in b:

    .
    ├── index.js
    ├── package.json
    └── vendor
        └── a
            ├── index.js
            └── package.json
    

    Where b retains its dependency on a and b's package.json includes:

    {
      "name": "b",
      "dependencies": {
        "a": "file:vendor/a"
      }
    }
    

    NOTE The package is within the context and found by the buildpack.

    This will succeed.

    NOTE I'm using jobs for convenience but the principal applies.

    gcloud run jobs deploy b \
    --source=${PWD} \
    --project=${PROJECT} \
    --region=${REGION}
    
    Job [b] has successfully been deployed.
    

    ...and I'm able to run the Job successfully.