Entorno de ejecución de Node.js

El entorno de ejecución de Node.js es la pila de software encargada de instalar el código y las dependencias de tu aplicación y, luego, ejecutarla en el entorno flexible.

Versiones de Node.js

Node.js 20 usa paquetes de compilación. El motor Node.js predeterminado usa la versión más reciente de LTS. Para obtener la lista completa de las versiones de Node.js compatibles y su versión de Ubuntu correspondiente, consulta el programa de asistencia del entorno de ejecución.

Para usar una versión compatible de Node.js, debes hacer lo siguiente:

  • Instala la versión 420.0.0 o una posterior de gcloud CLI. Puedes actualizar las herramientas de la CLI si ejecutas el comando gcloud components update. Para ver la versión instalada, ejecuta el comando gcloud version.

  • Incluye la configuración runtime_config y operating_system en el archivo app.yaml para especificar un sistema operativo.

  • De manera opcional, especifica una versión de la siguiente manera:

    • Agrega la configuración runtime_version en el archivo app.yaml. De forma predeterminada, se usa la última versión de Node.js si no se especifica la configuración de runtime_version. Por ejemplo:

      • Para especificar Node.js 20 en Ubuntu 22, haz lo siguiente:

          runtime: nodejs
          env: flex
        
          runtime_config:
              operating_system: "ubuntu22"
              runtime_version: "20"
        
      • Para especificar la versión compatible de Node.js más reciente en Ubuntu 22, haz lo siguiente:

          runtime: nodejs
          env: flex
        
          runtime_config:
              operating_system: "ubuntu22"
        

        La configuración de runtime_version admite semver.

    • Incluye la versión compatible de Node.js más reciente en el archivo package.json de la aplicación mediante el campo engines. Cuando usas el campo engines para especificar una versión, la configuración runtime_version tiene prioridad. Para evitar fallas inesperadas, te recomendamos que especifiques una versión de Node.js en el campo engines, junto con runtime_version. Por ejemplo:

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

      La propiedad engines.node puede ser un rango semver. Si especificas esta propiedad, el entorno de ejecución descarga y, luego, instala la última versión de Node.js que coincida con el rango semver. Si no se encuentran coincidencias, la aplicación no se implementa y el entorno de ejecución muestra un error.

Versiones anteriores del entorno de ejecución

Para la versión 16 y anteriores del entorno de ejecución de de Node.js, especifica una versión en el archivo package.json de tu aplicación mediante el campo engines.

El siguiente ejemplo configura el entorno de ejecución para que utilice la actualización de Node 9:

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

La propiedad engines.node puede ser un rango semver. Si especificas esta propiedad, el entorno de ejecución descarga y, luego, instala la última versión de Node.js que coincida con el rango semver. Si no se encuentran coincidencias, la aplicación no se implementa y el entorno de ejecución muestra un mensaje de error.

Compatibilidad con otros entornos de ejecución de Node.js

Si necesitas usar una versión de Node.js que no es compatible, puedes crear un entorno de ejecución personalizado y seleccionar una imagen base válida con la La versión de Node.js que necesitas.

Para las imágenes base proporcionadas por Google o las imágenes base de Docker para Node.js, consulta Compila entornos de ejecución personalizados.

Administrador de paquetes

Durante la implementación, el entorno de ejecución utiliza el administrador de paquetes npm, yarn o Pnpm para instalar las dependencias y, luego, iniciar la aplicación. El administrador de paquetes se configura con la siguiente lógica:

  • El administrador de paquetes predeterminado es npm.
  • Si un archivo yarn.lock está presente en el directorio raíz de tu aplicación, en su lugar, el entorno de ejecución utiliza el administrador de paquetes yarn.
  • Solo para Node.js 18 y versiones posteriores, si hay un archivo pnpm-lock.yaml presente en el directorio raíz de tu aplicación, el entorno de ejecución usará el administrador de paquetes Pnpm en su lugar.
  • Si existe un package-lock.json, un yarn.lock o unpnpm-lock.yaml, tu implementación fallará y mostrará un mensaje de error. Si necesitas la información del archivo package-lock.json, debes especificar los otros archivos del administrador de paquetes en la sección skip_files de tu app.yaml para resolver qué administrador de paquetes usar.

Versión del administrador de paquetes

La imagen del entorno de ejecución busca utilizar la última actualización de yarn y la versión de npm que está disponible en la última actualización de Node.js LTS.

Puedes especificar una versión del administrador de paquetes diferente para utilizar en el archivo package.json de tu aplicación mediante el campo engines. En este caso, el entorno de ejecución se asegura de que el administrador de paquetes utilizado para la implementación tenga una versión que coincida con las especificaciones que se mencionan en el campo engines.

Si se proporciona una especificación de la versión yarn y npm, solo el administrador de paquetes que se utilizó para la implementación se actualizará de ser necesario. Esto ahorra tiempo de implementación, ya que no se instala una versión personalizada de un administrador de paquetes si en realidad no se utiliza para implementar tu aplicación.

En el siguiente ejemplo, se configura el entorno de ejecución para utilizar una versión personalizada de npm:

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

En el siguiente ejemplo, se configura el entorno de ejecución para utilizar una versión personalizada de yarn:

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

Las propiedades engines.npm y engines.yarn pueden ser un rango semver.

Dependencias

Durante la implementación, el entorno de ejecución utilizará el administrador de paquetes npm o yarn para instalar dependencias mediante la ejecución de npm install o yarn install. Consulta la sección Administrador de paquetes para obtener más información sobre cómo el entorno de ejecución selecciona el administrador de paquete que utiliza.

Además, si deseas obtener más información sobre la administración de paquetes Node.js en Google App Engine, consulta Cómo utilizar las bibliotecas Node.js.

Para habilitar el uso de los paquetes de Node.js que requieren extensiones nativas, los siguientes paquetes de Ubuntu están preinstalados en la imagen de Docker.

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

Si tu aplicación requiere dependencias adicionales del nivel del sistema operativo, deberás utilizar un entorno de ejecución personalizado basado en este entorno de ejecución para instalar los paquetes adecuados.

Secuencia de comandos de compilación de NPM

Para el entorno de ejecución de Node.js 18 y versiones posteriores, el entorno de ejecución ejecuta npm run build si se detecta una secuencia de comandos build en package.json de forma predeterminada. Si necesitas control adicional sobre tus pasos de compilación antes de iniciar tu aplicación, puedes proporcionar un paso de compilación personalizado si agregas una secuencia de comandos gcp-build a tu archivo package.json.

Para evitar que tu compilación ejecute la secuencia de comandos npm run build, debes hacer lo siguiente:

  • Agrega una secuencia de comandos gcp-build con un valor vacío en el archivo package.json: "gcp-build":"".
  • Agrega la variable de entorno de compilación GOOGLE_NODE_RUN_SCRIPTS con un valor vacío en el archivo app.yaml.

    build_env_variables:
      GOOGLE_NODE_RUN_SCRIPTS: ''
    
Para obtener más información sobre cómo especificar variables de entorno de compilación, consulta la sección build_env_variables en el archivo app.yaml.

Inicio de la aplicación

El entorno de ejecución inicia tu aplicación mediante npm start, que usa el comando especificado en package.json. Por ejemplo:

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

Tu secuencia de comandos de inicio debe iniciar un servidor web que responda a las solicitudes HTTP en el puerto definido por la variable del entorno PORT, por lo general, 8080.

Extiende el tiempo de ejecución

Puedes usar entornos de ejecución personalizados para agregar una funcionalidad adicional a la aplicación Node.js que se ejecuta en el entorno flexible de App Engine. Para configurar un entorno de ejecución personalizado, reemplaza la siguiente línea en tu archivo app.yaml:

runtime: nodejs

por esta línea:

runtime: custom

También debes agregar los archivos Dockerfile y .dockerignore en el mismo directorio que contiene el archivo app.yaml.

Visita la documentación Entornos de ejecución personalizados para obtener información sobre cómo definir un Dockerfile en entornos de ejecución personalizados.

Proxies HTTPS y de reenvío

App Engine finaliza la conexión HTTPS en el balanceador de cargas y reenvía la solicitud a tu aplicación. Algunas aplicaciones deben determinar la IP y el protocolo de la solicitud original. La dirección IP del usuario está disponible en el encabezado X-Forwarded-For estándar. Las aplicaciones que necesitan esta información deben configurar sus marcos de trabajo web para que confíen en el proxy.

Con Express.js, utiliza la configuración trust proxy:

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

Para obtener más información sobre cómo aplicar las conexiones HTTPS, consulta Cómo se controlan las solicitudes.

Variables de entorno

Las siguientes variables del entorno se configuran mediante el entorno de ejecución:

Variable de entorno Descripción
GAE_INSTANCE El nombre de la instancia actual.
GAE_MEMORY_MB La cantidad de memoria disponible para el proceso de la aplicación.
GAE_SERVICE El nombre del servicio especificado en el archivo app.yaml de tu aplicación; si no se especifica, se configura como default.
GAE_VERSION La etiqueta de versión de la aplicación actual.
GOOGLE_CLOUD_PROJECT El ID del proyecto asociado con la aplicación, que se puede ver en la consola de Google Cloud.
NODE_ENV Cuando se implementa tu aplicación, el valor es production.
PORT El puerto que recibirá las solicitudes HTTP. Se define en 8080.

Puedes definir variables de entorno adicionales con app.yaml.

Servidor de metadatos

Cada instancia de tu aplicación puede usar el servidor de metadatos de Compute Engine para consultar información acerca de la instancia, incluidos el nombre del host, la dirección IP externa, el ID de la instancia, los metadatos personalizados y la información de la cuenta de servicio. App Engine no te permite definir metadatos personalizados para cada instancia; sin embargo, puedes definir metadatos personalizados de todo el proyecto y leerlos desde las instancias de App Engine y Compute Engine.

Esta función de ejemplo utiliza el servidor de metadatos para obtener la dirección IP externa de la instancia.

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.');
});