Environnement d'exécution Node.js

L'environnement d'exécution Node.js est la pile logicielle chargée d'installer le code et les dépendances de votre application, puis d'exécuter cette application dans l'environnement flexible.

  • Les versions 18 et ultérieures sont créées à l'aide de packs de création, ce qui nécessite de choisir un système d'exploitation dans votre fichier app.yaml. Par exemple, pour utiliser Node.js 20, vous devez spécifier Ubuntu 22 comme système d'exploitation.

  • Les versions 16 et antérieures sont créées à l'aide de Docker.

  • Le moteur par défaut Node.js utilise la dernière version LTS.

Pour obtenir la liste complète des versions de Node.js compatibles et de leur version correspondante, consultez le calendrier d'exécution.

Gestionnaire de packages

Lors du déploiement, l'environnement d'exécution utilise un gestionnaire de packages (npm, yarn ou Pnpm) 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.
  • Pour les environnements d'exécution Node.js version 18 et version 20, si un fichier pnpm-lock.yaml est présent dans le répertoire racine de votre application, l'environnement d'exécution utilise plutôt le gestionnaire de packages Pnpm.
  • Si le fichier package-lock.json et le fichier yarn.lock ou pnpm-lock.yaml existent, votre déploiement échouera et générera une erreur. Si vous avez besoin du fichier package-lock.json, vous devez spécifier les autres fichiers du gestionnaire de packages dans la section skip_files de votre fichier app.yaml pour déterminer le gestionnaire de packages à utiliser.

Choisir une version de Node.js

Nouvelles versions de l'environnement d'exécution

Pour les environnements d'exécution Node.js versions 18 et ultérieures, vous devez inclure les paramètres runtime_config et operating_system dans votre fichier app.yaml pour spécifier un système d'exploitation.

Pour utiliser les nouveaux environnements d'exécution, vous devez installer les versions 420.0.0 ou ultérieures de gcloud CLI. Vous pouvez mettre à jour les outils de la CLI en exécutant la commande gcloud components update. Pour afficher la version installée, vous pouvez exécuter la commande gcloud version.

Vous pouvez éventuellement spécifier une version en procédant comme suit :

  • Ajouter le paramètre runtime_version dans votre fichier app.yaml. Par défaut, la dernière version de Node.js est utilisée si le paramètre runtime_version n'est pas spécifié. Par exemple,

    • Pour spécifier Node.js 20 sur Ubuntu 22, procédez comme suit :
      runtime: nodejs
      env: flex
    
      runtime_config:
          operating_system: "ubuntu22"
          runtime_version: "20"
    
    • Pour spécifier la dernière version compatible de Node.js sur Ubuntu 22, procédez comme suit :
      runtime: nodejs
      env: flex
    
      runtime_config:
          operating_system: "ubuntu22"
    
  • Incluez toute version de Node.js dans le fichier package.json de votre application à l'aide du champ engines. Notez que lorsque vous utilisez le champ engines pour spécifier une version, le paramètre runtime_version est prioritaire. Pour éviter les failles inattendues, nous vous recommandons de spécifier une version de Node.js dans le champ engines. Par exemple,

      {
        "engines": {
          "node": "20.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.

Versions précédentes de l'environnement d'exécution

Pour les versions 16 et antérieures de l'environnement d'exécution Node.js, spécifiez une version dans le fichier package.json de votre application à l'aide du champ engines.

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.

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

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.

Script de compilation NPM

Pour les environnements d'exécution Node.js version 18 et ultérieure, l'environnement d'exécution exécute npm run build si un script build est détecté dans package.json par défaut. Si vous avez besoin d'exercer un contrôle supplémentaire sur vos étapes de compilation avant de démarrer votre application, vous pouvez fournir une étape de compilation personnalisée en ajoutant un script gcp-build à votre fichier package.json.

Pour empêcher votre compilation d'exécuter le script npm run build, vous devez effectuer l'une des opérations suivantes :

  • Ajoutez un script gcp-build avec une valeur vide dans votre fichier package.json : "gcp-build":"".
  • Ajoutez la variable d'environnement de compilation GOOGLE_NODE_RUN_SCRIPTS avec une valeur vide dans votre fichier app.yaml.

    build_env_variables:
      GOOGLE_NODE_RUN_SCRIPTS: ''
    
Pour en savoir plus sur la spécification des variables d'environnement de compilation, consultez la section build_env_variables du fichier app.yaml.

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 utiliser des environnements d'exécution personnalisés pour ajouter des fonctionnalités à une application Node.js exécutée dans l'environnement flexible App Engine. Pour configurer un environnement d'exécution personnalisé, remplacez la ligne suivante dans votre fichier app.yaml :

runtime: nodejs

par ce qui suit :

runtime: custom

Vous devez également ajouter les fichiers Dockerfile et .dockerignore dans le même répertoire que celui contenant le fichier app.yaml.

Pour découvrir comment définir un fichier Dockerfile dans un environnement d'exécution personnalisé, consultez la documentation sur les environnements d'exécution personnalisés.

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 pour les versions d'exécution Node.js 16 et antérieures et les versions 18 et ultérieures. Notez que vous devez mettre à jour votre fichier app.yaml pour utiliser la nouvelle version. Pour en savoir plus sur l'utilisation de versions plus récentes, consultez la page Environnement d'exécution Node.js.

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