The main application logic

There is no easy way around this, but our main application logic file, index.js, won't be as simple as the other configuration files have been:

'use strict'

// Load our dependencies
const bodyParser = require('body-parser')
const express = require('express');
const mongo = require('mongodb')

// Setup database and server constants
const DB_NAME = 'word_database';
const DB_HOST = process.env.DB_HOST || 'localhost:27017';
const COLLECTION_NAME = 'words';
const SERVER_PORT = 8000;

// Create our app, database clients, and the word list array
const app = express();
const client = mongo.MongoClient();
const dbUri = `mongodb://${DB_HOST}/${DB_NAME}`;
const words = [];

// Setup our templating engine and form data parser
app.set('view engine', 'pug')
app.use(bodyParser.urlencoded({ extended: false }))

// Load all words that are in the database
function loadWordsFromDatabase() {
return client.connect(dbUri).then((db) => {
return db.collection(COLLECTION_NAME).find({}).toArray();
})
.then((docs) => {
words.push.apply(words, docs.map(doc => doc.word));
return words;
});
}

// Our main landing page handler
app.get('/', (req, res) => {
res.render('index', { words: words });
});

// Handler for POSTing a new word
app.post('/new', (req, res) => {
const word = req.body.word;

console.info(`Got word: ${word}`);
if (word) {
client.connect(dbUri).then((db) => {
db.collection(COLLECTION_NAME).insertOne({ word }, () => {
db.close();
words.push(word);
});
});
}

res.redirect('/');
});

// Start everything by loading words and then starting the server
loadWordsFromDatabase().then((words) => {
console.info(`Data loaded from database (${words.length} words)`);
app.listen(SERVER_PORT, () => {
console.info("Server started on port %d...", SERVER_PORT);
});
});

This file may seem daunting at first, but this is possibly the smallest API service that you can make from scratch that is also fully functional.

If you would like to learn more about either Node, Express, or the MongoDB driver, you can visit https://nodejs.org/en/, https://expressjs.com/, and https://github.com/mongodb/node-mongodb-native. If you don't feel like typing, you can also copy and paste this file from https://github.com/sgnn7/deploying_with_docker/.

The basic operation of this app is as follows:

  • Load any existing words from the MongoDB database
  • Keep a copy of that list in a variable so that we only need to fetch things from the database once
  • Open a port 8000 and listen for requests
  • If we receive a GET request on /, return the rendered index.html template and fill it in with the word list array
  • If we receive a POST to /new:
    • Save the value in the database
    • Update our word list
    • Send us back to /

One part here, however, needs special attention:

const DB_HOST = process.env.DB_HOST || 'localhost:27017';

Remember when we previously mentioned that much of image configuration should be done through environment variables before? That is exactly what we are doing here! If an environment variable DB_HOST is set (as we expect it to be when running as a container), we will use it as the hostname, but if none is provided (as we expect it when running locally), it will assume that the database is running locally on the standard MongoDB port. This provides the flexibility of being configurable as a container and being able to be tested locally by a developer outside of Docker.

With the main logic file in place, our service should now be arranged in a similar filesystem layout as this:

$ tree ./
./
├── Dockerfile
├── index.js
├── package.json
└── views
└── index.pug

1 directory, 4 files

Since this is really the only easy part to test out of the three, let's install MongoDB locally and see what the service does. You can visit https://docs.mongodb.com/manual/installation/ for information on how to install it for other platforms, but I've included the following steps to do this manually on Ubuntu 16.04:

$ # Install MongoDB
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
$ echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list

$ sudo apt-get update
$ sudo apt-get install -y mongodb-org
$ sudo systemctl start mongodb

$ # Install our service dependencies
$ npm install
[email protected] /home/sg/checkout/deploying_with_docker/chapter_3/prototype_service/application_server
<snip>
npm WARN [email protected] No license field.

$ # Run the service</strong>
$ npm start
> [email protected] start /home/sg/checkout/deploying_with_docker/chapter_3/prototype_service/application_server
> node index.js

Data loaded from database (10 words)
Server started on port 8000...

It seems to work: let's check out the browser by going to http://localhost:8000!

Let's put a few words in it and see what happens:

So far, so good! The final test is restarting the service and making sure that we see the same list. Press Ctrl + C out of our Node process and run npm start. You should see the same list again, which means that it is working as expected!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset