How to start a microservice

This article described how to start a new microservice, written in Node.js.

Now into more details.

Files structure

These files/folders are common for all the modules.

  • config/ - folder for storing configs

  • lib/ - application data, functions etc.

  • lib/bugsnag.js - Bugsnag, the error tracking tool

  • lib/constants.js - constants used over the project

  • lib/errors.js - errors processing

  • lib/helpers.js - helpers used over the project

  • lib/logger.js - logging library (Bunyan)

  • lib/mailer.js - oms-mailer integration

  • lib/metrics.js - Prometheus metrics

  • lib/middlewares.js - common middlewares (authorizing, errors processing etc.)

  • lib/morgan.js - Morgan (library for logging requests)

  • lib/run.js - file to run the whole app

  • lib/server.js - list of all endpoints and the place where they are mounted

  • lib/sequelize.js - Sequelize, the ORM for Postgres

  • docker/ - Docker stuff, see below

  • models/ - ORM models for Sequelize

  • migrations/ - db migrations

  • test/ - everything related to testing

  • test/api - testing API requests

  • test/assets - all files/other services' responses used for testing

  • test/scripts - helpers/stub data generators/mocks

  • package.json - app manifesto basically

How Express works

All microservices use Express as a web framework. The idea is the following: on each endpoint (HTTP verb + path) some middlewares are mounted and executed consequently.

Dependencies you may need

You can install deps via npm install <name>

  • express - Express router

  • sequelize - Sequelize, the ORM for postgres database

  • morgan - logging requests

  • bunyan - logger

  • express-promise-router - a wrapper to have async middlewares

  • multer - processing files uploaded

  • request + request-promise-native - requests to other services

  • moment - working with dates

Dev dependencies (install via npm install -D <name>)

  • jest - testing framework

  • eslint - static code analysis

  • codecov - integration with CodeCov, code coverage service

  • nyc - test runner

  • nock - mock all external requests

  • commitlint - forces you to follow the conventional commit names

  • husky - custom git hooks

  • semantic-release - used in CI to automatucally bump versions on commits to master

Docker stuff

Everything that is in docker/ folder relates to how the app is executed (all microservices in our setup are set of docker containers). There's a folder structure as well:

  • docker/docker-compose.yml - a .yml file which is a manifesto of docker: which containers to run, which volumes to mount, what env params to pass etc.

  • docker/docker-compose.dev.yml - same but for dev setup (for dev setup, both docker-compose.yml and then docker-compose.dev.yml are used)

  • docker/*/Dockerfile - Dockerfile (basically a sequence of steps used to build the container)

On development mode, you build the container on a host machine.
On production, when you merge to master, a CI should build the container and push it to Dockerhub, then you pull the ready-to-use container on production server and use it.

Also there's a thing called traefik, which processes all requests going to the system, then mapping them to services based on URLs/hosts/headers/whatever. It's configured via docker-compose.yml labels. For example, everything that has '/services/oms-events/api' as a prefix is sent to oms-events with this prefix stripped.

Wiring it all to oms-docker

You do this:

  1. edit the oms-docker/.env file and change this:

  • add your service to ENABLED_SERVICES

  • add PATH_OMS_<insert-your-service-name> vars pointing to your <service-name>/docker folder, which (the variable) should also be in docker/*.yml folder

  • make start, then the app should start

If you want to store some static information to store (like users' avatars etc), you'll probably need another nginx container to serve static to end users, check out oms-events and oms-statutory on using it.

Also it's strongly advised to have a lot of tests on a backend so you'd have 100% code coverage everywhere, it helps a lot.

This describes how to start a backend, for frontend this is a (not complete) list to have it running:

  • add some new components

  • add some new menu entries

  • add it to router to process some URLs on the frontend

  • test it together with the backend to validate it's running

  • make a PR to oms-frontend, wait till it's merged

  • ???

  • PROFIT