Node JS Image Delivery Microservice Challenge [Docker, Node JS & MongoDB]

 

Continuation from http://justcodesnippets.durlut.ro/index.php/2019/12/08/node-js-image-delivery-microservice-challenge-mongo-db-stats-page/

We have to make the app self reliant.

We install Docker. We create the docker files.

FROM node:12
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

version: '3'
services:
  app:
    container_name: docker-node-mongo
    restart: always
    build: .
    ports:
      - '3000:3000'
    links:
      - mongo
  mongo:
    container_name: mongo
    image: mongo
    ports:
      - '27017:27017'

 

We make the app run on port 3000 to avoid conflicts.

We un-install mongodb and install mongoose client npm install mongoose

We re-write the DB client according to here:

// https://know-thy-code.com/mongoose-schemas-models-typescript/
import { connect, connection, Connection } from "mongoose";
import { IImageModel, Image } from "./image-schema";

declare interface IModels {
    Image: IImageModel;

}

export class DbClient {

    public static get Models() {
        if (!DbClient.instance) {
            DbClient.instance = new DbClient();
        }
        return DbClient.instance.models;
    }

    public static incrementImageValues(imageName: string, incrementTimesServed: boolean, incrementTimesResized: boolean, incrementTimesDirectlyServed: boolean) {
        DbClient.Models.Image.findOneAndUpdate({
            imageName
        }
            , {
                $inc: {
                    timesServed: incrementTimesServed ? 1 : 0
                    , timesResized: incrementTimesResized ? 1 : 0
                    , timesDirectlyServed: incrementTimesDirectlyServed ? 1 : 0
                }
            }, {
            new: true, upsert: true
        });
    }

    // https://mongoosejs.com/docs/promises.html
    public static async getImagesCollectionHtml(): Promise<string> {
        return DbClient.Models.Image.find({}).then(async (images) => {
            // write HTML output
            let output: string = "<html><header><title>Images</title></header><body>";
            output += "<h1>List retrieved from DB</h1>";
            output += '<table border="1">';
            output += `<tr> <td><b>Name</b></td><td><b>Nr of served images</b></td><td><b>Nr of times resized</b></td><td><b>Nr of times directly served</b></td></tr>`;

            // process list
            images.forEach((image) => {
                output += `<tr><td>${image.imageName}</td><td>${image.timesServed}</td><td>${image.timesResized}</td><td>${image.timesDirectlyServed}</td></tr>`;
            });

            // write HTML output (ending)
            output += "</table></body></html>";
            console.log(output);
            return output;
        });
    }

    private static instance: DbClient;

    private db: Connection;
    private models: IModels;

    private constructor() {
        connect("mongodb://mongo:27017/docker-node-mongo", { useNewUrlParser: true });
        this.db = connection;
        this.db.on("open", this.connected);
        this.db.on("error", this.error);

        this.models = {
            Image: new Image().model
            // this is where we initialise all models
        };
    }

    private connected() {
        console.log("Mongoose has connected");
    }

    private error(error: any) {
        console.log("Mongoose has errored", error);
    }

}

 

We run the docker command:  docker-compose up --build

After docker finishes building we call this address: http://localhost:3000/image/eye.jpg/600×300

And then this address: http://localhost:3000/image/cat.jpg/600×300

And then this address: http://localhost:3000/image/dog.jpg/600×300

And then the stats address http://localhost:3000/stats/

 

Leave a Reply

Your email address will not be published. Required fields are marked *