Building API Microservices into Docker containers each one with MongoDB and MySQL and API Gateway Pattern in Node.js
Published: 2022-05-28 01:17:06

**Hi, Devs!**

**Let's learn how to build API Microservices dockerized, each one with a specific database (MongoDB and MySQL) and make this available structuring an API Gateway pattern?**

_The complete project is here_: https://github.com/luizcalaca/microservices-nodejs-docker-gateway-api Do not forget to give it a star ⭐️ and play around with the code.

---

**What is Microservices and API Gateway pattern?**

- **Microservice Architecture** is an architectural way to build software that organize an application as a collection of small autonomous services thinking in a business domain.

- **API Gateway** is a way to centralize all routes that will be accessible through an endpoint. Why to use? Because we could have a lot of microservices in many containers with many routes, so would be a way to organize this amount.

---


Let's go on and look at image from [Azure](https://docs.microsoft.com/pt-br/dotnet/architecture/microservices/architect-microservice-container-applications/direct-client-to-microservice-communication-versus-the-api-gateway-pattern), here we are going to build de Microservices and the API Gateway with its endpoint to the client.
![API Gateway](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/227etdqwlykpto84svz1.png)

We can create threes folders each one with its _index.js_ and Node.js:
`
mkdir orders && cd orders && npm init -y && touch index.js
mkdir products && cd orders && npm init -y && touch index.js
mkdir api-gateway && cd gateway && npm init -y && touch index.js
`

_index.js_ orders:
```
const app = require('express')();

app.get('/orders', (req, res) => res.send('Hello Orders, API!'));

app.listen(3000, () => console.log(`Products API listening on port 3000!`));
```

_index.js_ products:
```
const app = require('express')();

app.get('/products', (req, res) => res.send('Hello Products, API with MySQL!'));

app.listen(3000, () => console.log(`Products API listening on port 3000!`));
```

_index.js_ api-gateway:
```
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();
const port = 3007;

const {
  ORDERS_API_URL,
  PRODUCTS_API_URL,
} = require('./URLs');

const optionsProducts = {
  target: PRODUCTS_API_URL,
  changeOrigin: true, 
  logger: console,
};

const optionsOrders = {
  target: ORDERS_API_URL,
  changeOrigin: true, 
  logger: console,
};

const productsProxy = createProxyMiddleware(optionsProducts);
const ordersProxy = createProxyMiddleware(optionsOrders);

app.get('/', (req, res) => res.send('Hello Gateway API'));
app.get('/orders', ordersProxy);
app.get('/products', productsProxy);

app.listen(port, () => console.log(`Example app listening on port ${port}!`));
```

_URLs.js_ in the same _index.js file_ hierarchy on api-gateway:

```
module.exports = {
    ORDERS_API_URL: 'http://localhost:3005',
    PRODUCTS_API_URL: 'http://localhost:3006',
  };
```

Add the _npm start_ script in all package.json:

```
 "scripts": {
    "start": "node index.js"
  }
```

After let's install express and express-http-proxy:

`
cd orders && npm i express
cd orders && npm i express
cd api-gateway && npm i express express-http-proxy
`
 
Let's create the Dockerfile and docker-compose.yaml, first the _orders_ with _MongoDB_ image:

```
FROM node:alpine
WORKDIR /usr/app
COPY package*.json ./
RUN npm install 
COPY . . 
EXPOSE 3000
CMD npm start
```

```
version: "3"

services:
  app:
    build: .
    command: npm start
    ports:
      - "3005:3000"
    volumes:
      - .:/usr/app
    depends_on:
      - "mongo"
    networks:
      - backend

  mongo:
    container_name: "mongo-node"
    platform: linux/amd64
    image: mongo:4.4.14
    ports:
      - "8081:8081"
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: root
    networks:
      - backend

networks:
  backend:
    driver: bridge
```

Second, the _products_ with MySQL database image:

```
FROM node:alpine
WORKDIR /usr/app
COPY package*.json ./
RUN npm install 
COPY . . 
EXPOSE 3000
CMD npm start
```

```
version: "3"

services:
  app:
    build: .
    command: npm start
    ports:
      - "3006:3000"
    volumes:
      - .:/usr/app
    depends_on:
      - "mysql"
    networks:
      - backend

  mysql:
    container_name: "data-node"
    platform: linux/amd64
    image: mysql:5.7.31
    command: --default-authentication-plugin=mysql_native_password --sql_mode=NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER --explicit_defaults_for_timestamp
    restart: always
    ports:
      - "3310:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - TZ=America/Sao_Paulo
    networks:
      - backend

networks:
  backend:
    driver: bridge
```

**How to run?**

- products microservice with MySQL
`cd /products
docker-compose up`

- orders microservice with MongoDB
`cd /orders
docker-compose up`

- API Gateway Pattern Architecture
`cd /api-gateway
npm start`

- Using API Gateway on browser
`http://localhost:3007/orders
http://localhost:3007/products`

**The complete project is here:** https://github.com/luizcalaca/microservices-nodejs-docker-gateway-api Do not forget to give it a star ⭐️ and play around with the code.

_**"That's all folks!"**_

**Contacts**
Email: luizcalaca@gmail.com
Instagram: https://www.instagram.com/luizcalaca
Linkedin: https://www.linkedin.com/in/luizcalaca/
Twitter: https://twitter.com/luizcalaca