The Node.js runtime

The Node.js runtime is the software stack responsible for installing your application code and dependencies, and then running that application in the flexible environment.

  • Version 18 and later are built using buildpacks, which requires you to choose an operating system in your app.yaml file. For example, to use Node.js 20, you must specify Ubuntu 22 as the operating system.

  • Version 16 and earlier are built using Docker.

  • The default Node.js engine uses the latest LTS release.

For the full list of supported Node.js versions, and their corresponding Ubuntu version, see the Runtime support schedule.

Package manager

During deployment, the runtime uses either the npm, or yarn, or Pnpm package manager to install dependencies and start the application. The package manager is set with the following logic:

  • The default package manager is npm.
  • If a yarn.lock file is present in your application's root directory, the runtime instead uses the yarn package manager.
  • For only Node.js runtimes version 18 and version 20, if a pnpm-lock.yaml file is present in your application's root directory, the runtime instead uses the Pnpm package manager.
  • If both a package-lock.json, and yarn.lock or pnpm-lock.yaml exist, your deployment will fail with an error. If you need the package-lock.json file, you must specify the other package manager files in the skip_files section of your app.yaml file to resolve which package manager to use.

Choose a Node.js version

New runtime versions

For Node.js runtime version 18 and later, you must include the runtime_config and operating_system settings in your app.yaml file to specify an operating system.

To use the new runtimes, you must install gcloud CLI version 420.0.0 or later. You can update your CLI tooling by running the gcloud components updatecommand. To view your installed version, you can run the gcloud version command.

Optionally, specify a version by:

  • Adding the runtime_version setting in your app.yaml file. By default, the latest Node.js version is used if the runtime_version setting is not specified. For example,

    • To specify Node.js 20 on Ubuntu 22:
      runtime: nodejs
      env: flex
    
      runtime_config:
          operating_system: "ubuntu22"
          runtime_version: "20"
    
    • To specify the latest supported Node.js version on Ubuntu 22:
      runtime: nodejs
      env: flex
    
      runtime_config:
          operating_system: "ubuntu22"
    
  • Including any Node.js version in your application's package.json file using the engines field. Note that when you use the engines field to specify a version, the runtime_version setting takes precedence. To prevent unexpected breakages, it is recommended that you specify a Node.js version in the engines field. For example,

      {
        "engines": {
          "node": "20.x"
        }
      }
    

    The engines.node property can be a semver range. If you specify this, the runtime downloads and installs the latest version of Node.js that matches the semver range. If no match is found, the application will fail to deploy and the runtime will return an error message.

Previous runtime versions

For Node.js runtime version 16 and earlier, specify a version in your application's package.json file using the engines field.

The following example configures the runtime to use the latest Node 9 release.

{
  "engines": {
    "node": "9.x"
  }
}

The engines.node property can be a semver range. If you specify this, the runtime downloads and installs the latest version of Node.js that matches the semver range. If no match is found, the application will fail to deploy and the runtime will return an error message.

Package manager version

The runtime image aims to use the latest yarn release and the release of npm that is available in the latest Node.js LTS release.

You can specify a different package manager version to use in your application's package.json file by using the engines field. In this case, the runtime will ensure that the package manager used for the deployment has a version that matches the specification listed in the engines field.

If both a yarn and npm version specification is given, only the package manager that is used for the deployment will be updated if needed. This saves deployment time by not installing a custom version of a package manager if it is not actually being used to deploy your application.

The following example configures the runtime to use a custom version of npm:

{
  "engines": {
    "npm": "5.x"
  }
}

The next example configures the runtime to use a custom version of yarn:

{
  "engines": {
    "yarn": ">=1.0.0 <2.0.0"
  }
}

The engines.npm and engines.yarn properties can both be a semver range.

Dependencies

During deployment, the runtime will use either the npm or yarn package manager to install dependencies by running npm install or yarn install. See the Package Manager section for more information on how the runtime selects the package manager to use.

Also, for more information about managing Node.js packages on Google App Engine, see Using Node.js Libraries.

To enable the use of Node.js packages that require native extensions, the following Ubuntu packages are pre-installed in the Docker image.

  • build-essential
  • ca-certificates
  • curl
  • git
  • imagemagick
  • libkrb5-dev
  • netbase
  • python

If your application requires additional operating-system-level dependencies, you will need to use a custom runtime based on this runtime to install the appropriate packages.

NPM build script

For Node.js runtime version 18 and later, the runtime environment executes npm run build if a build script is detected in package.json by default. If you require additional control over your build steps before starting your application, you can provide a custom build step by adding a gcp-build script to your package.json file.

To prevent your build from running the npm run build script, you must either:

  • Add a gcp-build script with an empty value in your package.json file: "gcp-build":"".
  • Add the GOOGLE_NODE_RUN_SCRIPTS build environment variable with an empty value in your app.yaml file.

    build_env_variables:
      GOOGLE_NODE_RUN_SCRIPTS: ''
    
For details about specifying build environment variables see build_env_variables section in the app.yaml file.

Application startup

The runtime starts your application by using npm start, which uses the command specified in package.json. For example:

"scripts": {
  "start": "node app.js"
}

Your start script should start a web server that responds to HTTP requests on the port specified by the PORT environment variable, typically 8080.

Extending the runtime

You can use custom runtimes to add additional functionality to a Node.js app running in the App Engine flexible environment. To configure a custom runtime, replace the following line in your app.yaml file:

runtime: nodejs

with this line:

runtime: custom

You must also add Dockerfile and .dockerignore files in the same directory that contains the app.yaml file.

Visit the Custom runtimes documentation to learn how to define a Dockerfile in a custom runtime.

HTTPS and forwarding proxies

App Engine terminates the HTTPS connection at the load balancer and forwards the request to your application. Some applications need to determine the original request IP and protocol. The user's IP address is available in the standard X-Forwarded-For header. Applications that require this information should configure their web framework to trust the proxy.

With Express.js, use the trust proxy setting:

app.set('trust proxy', true);

For information on enforcing HTTPS connections, see How Requests are Handled.

Environment variables

The following environment variables are set by the runtime environment:

Environment variable Description
GAE_INSTANCE The name of the current instance.
GAE_MEMORY_MB The amount of memory available to the application process.
GAE_SERVICE The service name specified in your application's app.yaml file, or if no service name is specified, it is set to default.
GAE_VERSION The version label of the current application.
GOOGLE_CLOUD_PROJECT The Project ID associated with your application, which is visible in the Google Cloud console
NODE_ENV When your app is deployed, the value is production.
PORT The port that will receive HTTP requests. Set to 8080.

You can set additional environment variables with app.yaml.

Metadata server

Each instance of your application can use the Compute Engine metadata server to query information about the instance, including its host name, external IP address, instance ID, custom metadata, and service account information. App Engine does not allow you to set custom metadata for each instance, but you can set project-wide custom metadata and read it from your App Engine and Compute Engine instances.

This example function uses the metadata server to get the external IP address of the instance for Node.js runtime version 16 and earlier, and version 18 and later. Note that you must update your app.yaml to use the new version. See Node.js runtime for more information about using newer versions.

const express = require('express');
const fetch = require('node-fetch');

const app = express();
app.enable('trust proxy');

const METADATA_NETWORK_INTERFACE_URL =
  'http://metadata/computeMetadata/v1/' +
  '/instance/network-interfaces/0/access-configs/0/external-ip';

const getExternalIp = async () => {
  const options = {
    headers: {
      'Metadata-Flavor': 'Google',
    },
    json: true,
  };

  try {
    const response = await fetch(METADATA_NETWORK_INTERFACE_URL, options);
    const ip = await response.json();
    return ip;
  } catch (err) {
    console.log('Error while talking to metadata server, assuming localhost');
    return 'localhost';
  }
};

app.get('/', async (req, res, next) => {
  try {
    const externalIp = await getExternalIp();
    res.status(200).send(`External IP: ${externalIp}`).end();
  } catch (err) {
    next(err);
  }
});

const PORT = parseInt(process.env.PORT) || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});