we’ll build a NodeJS microservice and deploy it using a Docker compose on the local system or you can your infra like Azure or AWS.
Here are the tools we’re going to use:
-
NodeJS version 10.0
-
Mysql
-
Redis
-
React App using create-react-app
-
MongoDB 3.4.1
-
Docker for Mac
Before you attempt this guide, you should have:
-
Basic knowledge in NodeJS
-
Basic knowledge in Docker (and Docker installed)
-
Basic knowledge in MongoDB (and the database service running. If you don’t, I suggest you follow my previous article How deploy a MongoDB replica set with Docker.)
But first, what is a microservice?
A microservice is a single self-contained unit which, together with many others, makes up a large application. By splitting your app into small units every part of it is independently deployable and scalable, can be written by different teams and in different programming languages and can be tested individually. — Max Stoiber A microservice architecture means that your app is made up of lots of smaller, independent applications capable of running in their own memory space and scaling independently from each other across potentially many separate machines. — Eric Elliot
The benefits of microservices
-
The application starts faster, which makes developers more productive, and speeds up deployments.
-
Each service can be deployed independently of other services — easier to deploy new versions of services frequently
-
Easier to scale development and can also have performance advantages.
-
Eliminates any long-term commitment to a technology stack. When developing a new service you can pick a new technology stack.
-
Microservices are typically better organized, since each microservice has a very specific job, and is not concerned with the jobs of other components.
-
Decoupled services are also easier to recompose and reconfigure to serve the purposes of different apps (for example, serving both the web clients and public API).
The drawbacks of microservices
-
Developers must deal with the additional complexity of creating a distributed system.
-
Deployment complexity. In production, there is also the operational complexity of deploying and managing a system comprised of many different service types.
-
As you’re building a new microservice architecture, you’re likely to discover lots of cross-cutting concerns that you did not anticipate at design time.
-
We now need to worry about scaling or Containers and managing then to get them up and running all the time.
Our services will be deployed on containers and nginx will be the central point for routing of services to the correct containers
ssl_certificate /etc/nginx/ssl/pac.crt;
ssl_certificate_key /etc/nginx/ssl/pac.key;
server {
server_name ms-commerce.com;
listen 80;
listen 443 ssl;
location / {
proxy_pass http://ms_commerce_client:3003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api/ {
proxy_pass http://ms_commerce_auth:3001/api/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /admin/ {
proxy_pass http://ms_commerce_admin:3002/api/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /cart/ {
proxy_pass http://ms_commerce_cart:3004/api/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
We are going to create containers for different services like mysql, mongo and node js containers for deploying microservices for Shopping cart application
These all are different services managing different parts of application like shopping cart Admin has Admin APIs for services, Cart-Auth APIs to manage authentication in the application. They all are talking to different services and different data source and on top of that we do have nginx routing to decide where to connect for a service like
ms-commerce.com will render react client app running on port 3003
ms-commerce.com/api/ will connect with Auth container
ms-commerce.com/cart/ will connect with Cart container
ms-commerce.com/admin. will connect with admin container
Docker-compose file will manage the deployment of all containers together
version: '3.5'
services:
gateway:
image: nginx:1.11
ports:
- 80:80
- 443:443
volumes:
- ./proxy/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./proxy/ssl:/etc/nginx/ssl:ro
depends_on:
- ms_commerce_auth
- ms_commerce_admin
- ms_commerce_client
networks:
- ms_network
ms_mysql:
container_name: ms_mysql
image: mysql:5.7
volumes:
- ~/datadir/mysql:/var/lib/mysql
ports:
- 3306:3306
- 33060:33060
environment:
MYSQL_ROOT_PASSWORD: root
networks:
- ms_network
ms_commerce_mongo:
image: mongo
container_name: ms_commerce_mongo
restart: unless-stopped
volumes:
- ~/datadir/mongo:/data/db
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
networks:
- ms_network
ms_commerce_auth:
container_name: ms_commerce_auth
build: ./e-Commerce-Auth/
image: e-commerce-auth
volumes:
- ./e-Commerce-Auth/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3001:3001
- 9201:9201
depends_on:
- ms_mysql
networks:
- ms_network
ms_commerce_cart:
container_name: ms_commerce_cart
build: ./e-Commerce-Cart/
image: e-commerce-cart
volumes:
- ./e-Commerce-Cart/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3004:3004
- 9204:9204
depends_on:
- ms_mysql
networks:
- ms_network
ms_commerce_admin:
build: ./e-Commerce-Admin/
image: e-commerce-admin
container_name: ms_commerce_admin
environment:
- NODE_ENV=local
volumes:
- ./e-Commerce-Admin/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3002:3002
- 9202:9202
depends_on:
- ms_commerce_mongo
networks:
- ms_network
ms_commerce_client:
build: ./e-Commerce-Client/
image: e-commerce-client
container_name: ms_commerce_client
environment:
- NODE_ENV=local
volumes:
- ./e-Commerce-Client/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3003:3003
depends_on:
- ms_commerce_admin
- ms_commerce_auth
networks:
- ms_network
networks:
ms_network:
driver: bridge
name: ms_network
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a Compose file to configure your application’s services. Then, using a single command, you create and start all the services from your configuration. To learn more about all the features of Compose see the list of features.
Compose is great for development, testing, and staging environments, as well as CI workflows. You can learn more about each case in Common Use Cases.
Using Compose is basically a three-step process.
-
Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
-
Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
-
Lastly, run docker-compose up and Compose will start and run your entire app.
A docker-compose.yml looks like this:
version: '2'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: redis
For more information about the Compose file, see the Compose file reference.
Compose has commands for managing the whole lifecycle of your application:
-
Start, stop and rebuild services
-
View the status of running services
-
Stream the log output of running services
-
Run a one-off command on a service
This is a very basic setup where nginx is talking to Node API containers and they further getting data from MySQL and mongo containers.
Dockerfile file is almost the same for all containers
FROM node:carbon
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
# npm install
RUN npm install
# Run npm install --global grpc --unsafe-perm
EXPOSE 3004 9204
CMD [ "npm", "run", "watchserver" ]
CMD [ "npm", "run", "startdev" ]
We are writing code in typescript and using TSC compiler to generate build and deploying the building code using nodemon on containers.
Conclusion :
Write application and deploy them using Docker containers on your local.
I hope you enjoyed this article. I’m still exploring the NodeJS and the microservices world, so I’m open to accepting feedback and contributions.
If you enjoyed this article, recommend it to a friend.
Find out more
Learning how to use Bash commands with Docker CLI commands can help you work more effectively with Docker apps. Check out the Docker docs and my other posts to learn more.
Comments