Node.js

Node.js is a popular JavaScript runtime built on Chrome's V8 JavaScript engine. Platform.sh supports deploying Node.js applications quickly and easily. Using our Multi-App support you can build a micro-service oriented system mixing both Javascript and PHP applications.

Supported versions

  • 6.11
  • 8.9
  • 10

If you need other versions, take a look at our options for installing them with NVM.

Deprecated versions

The following versions are available but are not receiving security updates from upstream, so their use is not recommended. They will be removed at some point in the future.

  • 0.12
  • 4.7
  • 4.8
  • 6.9
  • 6.10
  • 8.2

Support libraries

While it is possible to read the environment directly from your application, it is generally easier and more robust to use the platformsh-config NPM library which handles decoding of service credential information for you.

Configuration

To use Platform.sh and Node.js together, configure the .platform.app.yaml file with a few key settings, as described here (a complete example is included at the end).

  1. Specify the language of your application (available versions are listed above):

    # .platform.app.yaml
    type: "nodejs:10"
    
  2. Specify your dependencies under the nodejs key, like this:

    dependencies:
      nodejs:
        pm2: "^2.5.0"
    

    These are the global dependencies of your project (the ones you would have installed with npm install -g). Here we specify the pm2 process manager that will allow us to run the node process.

  3. Configure the command you use to start serving your application (this must be a foreground-running process) under the web section, e.g.:

    web:
      commands:
        start: "PM2_HOME=/app/run pm2 start index.js --no-daemon"
    

    If there is a package.json file present at the root of your repository, Platform.sh will automatically install the dependencies. We suggest including the platformsh-config helper npm module, which makes it trivial to access the running environment.

    {
      "dependencies": {
        "platformsh-config": "^2.0.0"
      }
    }
    
  4. Create any Read/Write mounts. The root file system is read only. You must explicitly describe writable mounts. In (3) we set the home of the process manager to /app/run so this needs to be writable.

    mounts:
        run:
            source: local
            source_path: run
    
  5. Include any relevant commands needed to build and setup your application in the hooks section, e.g.:

    hooks:
      build: |
        npm install
        npm run build
        bower install
    
  6. Setup the routes to your Node.js application in .platform/routes.yaml.

    "https://{default}/":
      type: upstream
      upstream: "app:http"
    
  7. (Optional) If Platform.sh detects a package.json file in your repository, it will automatically include a default build flavor, that will run npm prune --userconfig .npmrc && npm install --userconfig .npmrc. You can modify that process to use an alternative package manager by including the following in your .platform.app.yaml file:

    build:
      flavor: none
    

    Consult the documentation specific to Node.js builds for more information.

Here's a complete example that also serves static assets (.png from the /public directory):

name: node
type: nodejs:10

web:
  commands:
    start: "PM2_HOME=/app/run pm2 start index.js --no-daemon"
    #in this setup you will find your application stdout and stderr in /app/run/logs
  locations:
    "/public":
      passthru: false
      root: "public"
      # Whether to allow files not matching a rule or not.
      allow: true
      rules:
        '\.png$':
          allow: true
          expires: -1
dependencies:
  nodejs:
    pm2: "^2.5.0"
mounts:
   run:
       source: local
       source_path: run
disk: 512

In your application...

Finally, make sure your Node.js application is configured to listen over the port given by the environment (here we use the platformsh helper and get it from config.port) that is available in the environment variable PORT. Here's an example:

// Load the http module to create an http server.
const http = require('http');

// Load the Platform.sh configuration
const config = require('platformsh-config').config();

const server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/html"});
  response.end("<html><head><title>Hello Node.js</title></head><body><h1><img src='public/js.png'>Hello Node.js</h1><h3>Platform configuration:</h3><pre>"+JSON.stringify(config, null, 4) + "</pre></body></html>");
});

server.listen(config.port);

Accessing services

To access various services with Node.js, see the following examples. The individual service pages have more information on configuring each service.

Elasticsearch
Memcached
MongoDB
MySQL
PostgreSQL
Redis
Solr
const elasticsearch = require('elasticsearch');
const config = require("platformsh-config").config();

exports.usageExample = async function() {

    const credentials = config.credentials('elasticsearch');

    var client = new elasticsearch.Client({
        host: `${credentials.host}:${credentials.port}`,
    });


    let index = 'my_index';
    let type = 'People';

    // Index a few document.
    let names = ['Ada Lovelace', 'Alonzo Church', 'Barbara Liskov'];

    let message = {
        refresh: "wait_for",
        body: []
    };
    names.forEach((name) => {
        message.body.push({index: {_index: index, _type: type}});
        message.body.push({name: name});
    });
    await client.bulk(message);

    // Search for documents.
    const response = await client.search({
        index: index,
        q: 'name:Barbara Liskov'
    });

    let output = '';

    if(response.hits.total > 0) {
        output += `<table>
        <thead>
        <tr><th>ID</th><th>Name</th></tr>
        </thead>
        <tbody>`;
        response.hits.hits.forEach((record) => {
            output += `<tr><td>${record._id}</td><td>${record._source.name}</td></tr>\n`;
        });
        output += "</tbody>\n</table>\n";
    }

    // Clean up after ourselves.
    response.hits.hits.forEach((record) => {
        client.delete({
            index: index,
            type: type,
            id: record._id,
        });
    });

    return output;
};
const Memcached = require('memcached');
const config = require("platformsh-config").config();
const { promisify } = require('util');

exports.usageExample = async function() {

    const credentials = config.credentials('memcached');

    let client = new Memcached(`${credentials.host}:${credentials.port}`);

    // The MemcacheD client is not Promise-aware, so make it so.
    const memcachedGet = promisify(client.get).bind(client);
    const memcachedSet = promisify(client.set).bind(client);

    let key = 'Deploy-day';
    let value = 'Friday';

    // Set a value.
    await memcachedSet(key, value, 10);

    // Read it back.
    let test = await memcachedGet(key);

    let output = `Found value <strong>${test}</strong> for key <strong>${key}</strong>.`;

    return output;
};
const mongodb = require('mongodb');
const config = require("platformsh-config").config();

exports.usageExample = async function() {
    const credentials = config.credentials('mongodb');
    const MongoClient = mongodb.MongoClient;

    var client = await MongoClient.connect(config.formattedCredentials('mongodb', 'mongodb'));

    let db = client.db(credentials["path"]);

    let collection = db.collection("startrek");

    const documents = [
        {'name': 'James Kirk', 'rank': 'Admiral'},
        {'name': 'Jean-Luc Picard', 'rank': 'Captain'},
        {'name': 'Benjamin Sisko', 'rank': 'Prophet'},
        {'name': 'Katheryn Janeway', 'rank': 'Captain'},
    ];

    await collection.insert(documents, {w: 1});

    let result = await collection.find({rank:"Captain"}).toArray();

    let output = '';

    output += `<table>
<thead>
<tr><th>Name</th><th>Rank</th></tr>
</thead>
<tbody>`;

    Object.keys(result).forEach((key) => {
        output += `<tr><td>${result[key].name}</td><td>${result[key].rank}</td></tr>\n`;
    });

    output += `</tbody>\n</table>\n`;

    // Clean up after ourselves.
    collection.remove();

    return output;
};
const mysql = require('mysql2/promise');
const config = require("platformsh-config").config();

exports.usageExample = async function() {

    const credentials = config.credentials('database');

    const connection = await mysql.createConnection({
        host: credentials.host,
        port: credentials.port,
        user: credentials.username,
        password: credentials.password,
        database: credentials.path,
    });

    let sql = '';

    // Creating a table.
    sql = `CREATE TABLE IF NOT EXISTS People (
        id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(30) NOT NULL,
            city VARCHAR(30) NOT NULL
        )`;
    await connection.query(sql);

    // Insert data.
    sql = `INSERT INTO People (name, city) VALUES
    ('Neil Armstrong', 'Moon'),
        ('Buzz Aldrin', 'Glen Ridge'),
        ('Sally Ride', 'La Jolla');`;
    await connection.query(sql);

    // Show table.
    sql = `SELECT * FROM People`;
    let [rows] = await connection.query(sql);

    let output = '';

    if (rows.length > 0) {
        output +=`<table>
            <thead>
            <tr><th>Name</th><th>City</th></tr>
            </thead>
            <tbody>`;

        rows.forEach((row) => {
            output += `<tr><td>${row.name}</td><td>${row.city}</td></tr>\n`;
        });

        output += `</tbody>\n</table>\n`;
    }

    // Drop table.
    sql = `DROP TABLE People`;
    await connection.query(sql);

    return output;
};
const pg = require('pg');
const config = require("platformsh-config").config();

exports.usageExample = async function() {

    const credentials = config.credentials('postgresql');

    const client = new pg.Client({
        host: credentials.host,
        port: credentials.port,
        user: credentials.username,
        password: credentials.password,
        database: credentials.path,
    });

    client.connect();

    let sql = '';

    // Creating a table.
    sql = `CREATE TABLE IF NOT EXISTS People (
      id SERIAL PRIMARY KEY,
      name VARCHAR(30) NOT NULL,
      city VARCHAR(30) NOT NULL
      )`;
    await client.query(sql);

    // Insert data.
    sql = `INSERT INTO People (name, city) VALUES 
        ('Neil Armstrong', 'Moon'), 
        ('Buzz Aldrin', 'Glen Ridge'), 
        ('Sally Ride', 'La Jolla');`;
    await client.query(sql);

    // Show table.
    sql = `SELECT * FROM People`;
    let result = await client.query(sql);

    let output = '';

    if (result.rows.length > 0) {
        output +=`<table>
            <thead>
            <tr><th>Name</th><th>City</th></tr>
            </thead>
            <tbody>`;

        result.rows.forEach((row) => {
            output += `<tr><td>${row.name}</td><td>${row.city}</td></tr>\n`;
        });

        output += `</tbody>\n</table>\n`;
    }

    // Drop table.
    sql = `DROP TABLE People`;
    await client.query(sql);

    return output;
};
const redis = require('redis');
const config = require("platformsh-config").config();
const { promisify } = require('util');

exports.usageExample = async function() {

    const credentials = config.credentials('redis');

    var client = redis.createClient(credentials.port, credentials.host);

    // The Redis client is not Promise-aware, so make it so.
    const redisGet = promisify(client.get).bind(client);
    const redisSet = promisify(client.set).bind(client);

    let key = 'Deploy day';
    let value = 'Friday';

    // Set a value.
    await redisSet(key, value);

    // Read it back.
    let test = await redisGet(key);

    let output = `Found value <strong>${test}</strong> for key <strong>${key}</strong>.`;

    return output;
};
const solr = require('solr-node');
const config = require("platformsh-config").config();

exports.usageExample = async function() {

    let client = new solr(config.formattedCredentials('solr', 'solr-node'));

    let output = '';

    // Add a document.
    var result = await client.update({
        id: 123,
        name: 'Valentina Tereshkova',
    });

    output += "Adding one document. Status (0 is success): " + result.responseHeader.status +  "<br />\n";

    // Flush writes so that we can query against them.
    await client.softCommit();

    // Select one document:
    let strQuery = client.query().q();
    result = await client.search(strQuery);
    output += "Selecting documents (1 expected): " + result.response.numFound + "<br />\n";

    // Delete one document.
    result = await client.delete({id: 123});
    output += "Deleting one document. Status (0 is success): " + result.responseHeader.status + "<br />\n";

    return output;
};

Project templates

A number of project templates for Node.js applications and typical configurations are available on GitHub. Not all of them are proactively maintained but all can be used as a starting point or reference for building your own website or web application.