El entorno de ejecución de Node.js

Descripción general

El entorno de ejecución de Node.js es la pila de software encargada de instalar el código de la aplicación y sus dependencias, y de ejecutar la aplicación. El entorno de ejecución se declara en app.yaml como runtime: nodejs:

runtime: nodejs
env: flex

Los entornos de ejecución en el entorno flexible se compilan con Docker. El entorno de ejecución de Node.js se basa en Ubuntu 16.04 y el código fuente para el entorno de ejecución de Node.js está disponible de forma pública en GitHub.

Administrador de paquetes

Durante la implementación, el entorno de ejecución utiliza el administrador de paquetes npm o yarn 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.
  • Si existe un package-lock.json y un yarn.lock, tu implementación fallará y mostrará un mensaje de error. Si necesitas ambos archivos, puedes agregar uno de ellos a la sección skip_files de tu archivo app.yaml para resolver qué administrador de paquetes utilizar.

Motores

Versión de Node.js

El motor de Node.js predeterminado busca ser la última actualización de LTS. Puedes especificar una versión diferente de Node.js en el archivo package.json de tu aplicación mediante el campo engines. Para impedir fallas inesperadas, debes especificar una versión de Node.js.

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

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

La propiedad engines.node puede ser un rango semver. Si especificas esto, 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 implementará y el entorno de ejecución mostrará un mensaje de error.

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 asegurará 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 Ubuntu están preinstalados en la imagen de Docker.

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.

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 entorno de ejecución

El entorno de ejecución estándar Node.js puede utilizarse para crear un entorno de ejecución personalizado. Para ello, utiliza gcloud beta app gen-config --custom a fin de crear la base de archivos Dockerfile y .dockerignore. Luego, puedes personalizar estos archivos según sea necesario. Ten en cuenta que, si creas Dockerfile, debes especificar runtime: custom en lugar de runtime: nodejs en tu archivo app.yaml.

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 del entorno

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

Variable del 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 Google Cloud Console
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 request = require('got');

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 {body} = await request(METADATA_NETWORK_INTERFACE_URL, options);
    return body;
  } 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 = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});