Fullstack JavaScript Microservice Web App in Minutes
--
This article shows how to quickly prototype a web app that consists of the following main architecture components:
- front-end service: NGINX web server + React.js app.
- front-end CSS library: Bootstrap.
- back-end service: Node.js + Express.js.
- worker service.
- database: MongoDB.
- message broker: RabbitMQ.
- Docker containers.
- deployment to AWS EC2.
We’re going to use the SMF framework, which helps generate the boilerplate code, connect the services and deploy them to AWS:
https://github.com/krawa76/smf
The demo app code is available here:
https://github.com/krawa76/smf-test-web-app
Requirements: Node.js and Docker with Docker Compose installed locally.
Create project
Install SMF, create a new project and cd to the project directory:
$ npm install -g sokyra-microservice-factory
$ smf new test-app
$ cd test-app
Add back-end service
$ smf add service back-endSelect service template:
1) Basic worker
2) Back-end (Express.js)
3) Front-end (React.js)prompt: number: 2
Add MongoDB and RabbitMQ services, and the corresponding Node.js client libraries:
0) exit selection
1) (message broker) RabbitMQ
2) (database) Memcached
3) (database) MongoDB
4) (database) MySQL
5) (database) PostgreSQL
6) (database) Redis
7) (search engine) Elasticsearchprompt: number: 3Selected clients:
[MongoDB]
Select another client:0) exit selection
1) (message broker) RabbitMQ
2) (database) Memcached
3) (database) MongoDB
4) (database) MySQL
5) (database) PostgreSQL
6) (database) Redis
7) (search engine) Elasticsearchprompt: number: 1
Add front-end service
Create the front-end service, point it to the existing back-end one:
$ smf add service front-endSelect service template:
1) Basic worker
2) Back-end (Express.js)
3) Front-end (React.js)prompt: number: 3Select a back-end service to connect to:
1: demo
2: back-endprompt: number: 2
Add worker service
Create the worker service, add the RabbitMQ message broker support:
$ smf add service workerSelect service template:
1) Basic worker
2) Back-end (Express.js)
3) Front-end (React.js)prompt: number: 1==================================================Select third-party services clients that your service "worker" connects to (one at a time),0) exit selection
1) (message broker) RabbitMQ
2) (database) Memcached
3) (database) MongoDB
4) (database) MySQL
5) (database) PostgreSQL
6) (database) Redis
7) (search engine) Elasticsearchprompt: number: 1
At this point all the boilerplate code modules and config files for the services and Docker stack are ready.
Run app
Let’s start our services and see how they work:
$ smf up
SMF builds Docker images and start containers. When they are running, we can check our web app in a browser:
What we see is a React.js / Bootstrap CSS application that receives the data from the back-end service.
We can also check what Docker containers are running behind the scenes:
$ docker ps
Here we see the front-end, back-end, worker, and demo services (added by default and can me removed), as well as MongoDB database and RabbitMQ message broker:
After we’re done with the testing, we can shut down the app (stop the Docker containers):
$ smf down
Project structure
Let’s inspect what we’ve got auto-generated out of the box so far… All the services code lives in one repo:
The other important modules are:
- smf-stack.json: project config.
- smf-env.json: environment variables.
- smf-deploy.json: deployment config.
Back-end structure
The entry point module main.ts
does the following:
- starts the web server.
- handles the
/kittens
endpoint. - inserts demo data into the database.
- sends demo messages to the message broker:
Front-end structure
The main modules here are:
- Dockerfile: builds the service image with NGINX web server embedded.
- nginx.conf: web server config.
- ./app folder: React.js application.
- ./app/src/App.js: main app module with routing.
- ./app/src/Api.js: API client.
- ./app/src/pages: Home, Kittens and NotFound pages.
- ./app/src/components: flash (alerts, errors, etc.) and navigation modules.
Worker structure
The main module shows how to work with shared modules and exchange demo messages with the message broker:
Fetch data from database
So far our back-end API returns the hard-coded demo data, see ./services/back-end/routes/kittens.ts
:
Let’s replace this logic with fetching the data from our kittens
db collection:
Start the app again and see the db data on UI:
$ smf up
Message broker
At this point, the back-end & worker services exchange demo messages using the demo.*
RabbitMQ channel. If you need to send some extra asynchronous jobs, you can establish an extra channel:
Develop / debug mode
Back-end: stop the Docker container, prepare SMF debug config:
$ docker stop test-app-back-end
$ smf debug back-end
Then open the project in VSCode and use “Start Debugging” menu (hit F5).
Front-end: start the React app, non-containerized:
$ docker stop test-app-front-end
$ cd services/front-end/app
$ npm start
Deploy
It’s easy to deploy our project to a remote server which has Docker & Docker-Compose installed. If you don’t have one so far, you can create it in Amazon AWS EC2 using the following simple instruction:
https://github.com/krawa76/smf/blob/master/README-provisioner.md
Docker Hub account is also required. You can sign up for free here if it’s missing:
Open smf-deploy.json
file in the editor and fill in the Docker Hub login/password, host address, and remote machine SSH credentials (ssh key path). Replace the EC2 public host name in BUILD_REACT_APP_API_URL
:
Run this command to deploy the project:
$ smf deploy
Ssh to the remote machine and see our microservices running there:
$ ssh -i "/Users/me/.ssh/aws-key.pem" ubuntu@ec2-x-x-x-x.compute1.amazonaws.com$ docker ps
(gives the list of services)
Open the deployed web app in the browser (specify your EC2 host name):
http://ec2-x-x-x-x.compute1.amazonaws.com
Conclusion
Congrats, you have a working prototype of a containerized microservice web app in the cloud!