L'environnement d'exécution Node.js

Aperçu

L'environnement d'exécution Node.js est la pile logicielle chargée d'installer le code de votre application et ses dépendances, et d'exécuter votre application. L'environnement d'exécution est déclaré dans le fichier app.yaml en tant que runtime: nodejs :

runtime: nodejs
env: flex

Les environnements d'exécution flexibles sont créés à l'aide de Docker. L'environnement d'exécution Node.js est basé sur Ubuntu 16.04. Son code source est publiquement accessible sur GitHub.

Gestionnaire de packages

Lors du déploiement, l'environnement d'exécution utilise un gestionnaire de packages (npm ou yarn) pour installer les dépendances et démarrer l'application. Le gestionnaire de packages est défini selon la logique suivante :

  • Le gestionnaire de packages par défaut est npm.
  • Si un fichier yarn.lock est présent dans le répertoire racine de votre application, l'environnement d'exécution utilise plutôt le gestionnaire de packages yarn.
  • Si les fichiers package-lock.json et yarn.lock existent, votre déploiement échouera et générera une erreur. Si vous avez besoin des deux fichiers, vous pouvez en ajouter un à la section skip_files de votre fichier app.yaml pour déterminer quel gestionnaire de packages utiliser.

Moteurs

Version Node.js

Le moteur par défaut Node.js a tendance à être la dernière version LTS. Vous pouvez spécifier une autre version de Node.js dans le fichier package.json de votre application à l'aide du champ engines. Pour éviter les failles inattendues, vous devez spécifier une version de Node.js.

L'exemple suivant configure l'environnement d'exécution pour qu'il utilise la dernière version de Node 9.

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

La propriété engines.node peut être une plage semver. Si vous la spécifiez, l'environnement d'exécution télécharge et installe la dernière version de Node.js qui correspond à la plage semver. Si aucune correspondance n'est trouvée, le déploiement de l'application échoue et l'environnement d'exécution renvoie un message d'erreur.

Version du gestionnaire de packages

L'image de l'environnement d'exécution vise à utiliser la dernière version de yarn et la version de npm disponible dans la version LTS de Node.js la plus récente.

Vous pouvez spécifier une autre version du gestionnaire de packages à utiliser dans le fichier package.json de votre application à l'aide du champ engines. Dans ce cas, l'environnement d'exécution s'assure que la version du gestionnaire de packages utilisée pour le déploiement correspond à la spécification indiquée dans le champ engines.

Si vous spécifiez une version yarn et une version npm, seul le gestionnaire de packages utilisé pour le déploiement sera mis à jour si nécessaire. Cela permet de gagner du temps de déploiement en n'installant pas de version personnalisée d'un gestionnaire de packages si celui-ci n'est pas réellement utilisé pour déployer votre application.

L'exemple ci-après configure l'environnement d'exécution de sorte qu'il utilise une version personnalisée de npm :

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

L'exemple suivant configure l'environnement d'exécution de sorte qu'il utilise une version personnalisée de yarn :

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

Les propriétés engines.npm et engines.yarn peuvent toutes deux être une plage semver.

Dépendances

Lors du déploiement, l'environnement d'exécution utilise un gestionnaire de packages (npm ou yarn) pour installer les dépendances en exécutant npm install ou yarn install. Consultez la section Gestionnaire de packages pour en savoir plus sur la manière dont l'environnement d'exécution sélectionne celui à utiliser.

De même, pour obtenir plus d'informations sur la gestion des packages Node.js dans Google App Engine, consultez la page Utiliser les bibliothèques Node.js.

Pour permettre l'utilisation de packages Node.js nécessitant des extensions natives, les packages Ubuntu suivants sont pré-installés dans l'image Docker.

Si votre application nécessite des dépendances supplémentaires au niveau du système d'exploitation, vous devrez installer les packages appropriés dans un environnement d'exécution personnalisé basé sur cet environnement d'exécution.

Démarrage de l'application

L'environnement d'exécution démarre votre application en utilisant npm start, qui utilise la commande spécifiée dans package.json. Exemple :

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

Votre script de démarrage doit démarrer un serveur Web qui répond aux requêtes HTTP sur le port spécifié par la variable d'environnement PORT, en général 8080.

Étendre l'environnement d'exécution

Vous pouvez vous servir de l'environnement d'exécution standard Node.js pour créer un environnement d'exécution personnalisé. Pour ce faire, utilisez gcloud beta app gen-config --custom pour créer les fichiers Dockerfile et .dockerignore de base. Vous pouvez ensuite personnaliser ces fichiers selon vos besoins. Notez que si vous créez Dockerfile, vous devez spécifier runtime: custom au lieu de runtime: nodejs dans votre fichier app.yaml.

HTTPS et proxy de transfert

App Engine met fin à la connexion HTTPS au niveau de l'équilibreur de charge et transfère la requête à votre application. Certaines applications doivent déterminer l'adresse IP et le protocole de la requête d'origine. L'adresse IP de l'utilisateur est disponible dans l'en-tête standard X-Forwarded-For. Les applications nécessitant ces informations doivent configurer leur framework Web pour qu'il fasse confiance au proxy.

Avec Express.js, utilisez le paramètre trust proxy :

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

Pour en savoir plus sur l'application des connexions HTTPS, consultez la page Mode de traitement des requêtes.

Variables d'environnement

Les variables d'environnement suivantes sont définies par l'environnement d'exécution :

Variable d'environnement Description
GAE_INSTANCE Le nom de l'instance actuelle.
GAE_MEMORY_MB La quantité de mémoire disponible pour le processus d'application.
GAE_SERVICE Nom du service spécifié dans le fichier app.yaml de votre application. Si aucun nom de service n'est spécifié, il est défini sur default.
GAE_VERSION Libellé de version de l'application en cours.
GOOGLE_CLOUD_PROJECT ID du projet associé à votre application, visible dans Google Cloud Console.
NODE_ENV Lorsque votre application est déployée, la valeur est production.
PORT Port qui reçoit les requêtes HTTP. Variable définie sur 8080.

Vous pouvez définir des variables d'environnement supplémentaires à l'aide du fichier app.yaml.

Serveur de métadonnées

Chaque instance de votre application peut utiliser le serveur de métadonnées Compute Engine pour demander des informations sur l'instance, y compris son nom d'hôte, son adresse IP externe, son ID d'instance, ses métadonnées personnalisées et ses informations de compte de service. App Engine ne vous permet pas de définir des métadonnées personnalisées pour chaque instance, mais vous pouvez définir des métadonnées personnalisées à l'échelle du projet et les lire à partir de vos instances App Engine et Compute Engine.

Cet exemple de fonction utilise le serveur de métadonnées afin d'obtenir l'adresse IP externe de l'instance :

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