Designing a Scalable Microservices Architecture With Docker, NGINX, and Node.js

Designing a Scalable Microservices Architecture With Docker, NGINX, and Node.js Building monoliths may be quicker for small apps, but scaling them can become a nightmare. Microservices break down your application into independent services that can scale and deploy separately. In this guide, we’ll walk through setting up a basic microservices architecture using Docker, NGINX as a reverse proxy, and Node.js services. Architecture Overview We’ll build two simple Node.js services: user-service and product-service. NGINX will route requests to the correct service, and Docker Compose will tie everything together. Step 1: Create the Project Structure microservices-app/ ├── nginx/ │ └── default.conf ├── user-service/ │ └── index.js ├── product-service/ │ └── index.js ├── docker-compose.yml Step 2: Create Node Services // user-service/index.js const express = require('express'); const app = express(); app.get('/users', (req, res) => res.json([{ id: 1, name: 'Alice' }])); app.listen(3001, () => console.log('User Service on port 3001')); // product-service/index.js const express = require('express'); const app = express(); app.get('/products', (req, res) => res.json([{ id: 101, name: 'Laptop' }])); app.listen(3002, () => console.log('Product Service on port 3002')); Step 3: Add Dockerfiles # Dockerfile for both services FROM node:18 WORKDIR /app COPY . . RUN npm install express CMD ["node", "index.js"] Step 4: Configure NGINX # nginx/default.conf server { listen 80; location /users { proxy_pass http://user-service:3001; } location /products { proxy_pass http://product-service:3002; } } Step 5: Compose Everything With Docker # docker-compose.yml version: '3' services: user-service: build: ./user-service ports: - "3001:3001" product-service: build: ./product-service ports: - "3002:3002" nginx: image: nginx:latest ports: - "80:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - user-service - product-service Step 6: Test Your Microservices Start the services with: docker-compose up --build Then visit: http://localhost/users → forwarded to user-service http://localhost/products → forwarded to product-service Conclusion This setup forms the foundation of a scalable microservices architecture. You can expand this by adding service discovery, authentication, logging, and container orchestration with Kubernetes. Microservices bring complexity, but when done right, they offer unmatched flexibility and scalability. If this post helped you, consider supporting me: buymeacoffee.com/hexshift

Apr 14, 2025 - 08:47
 0
Designing a Scalable Microservices Architecture With Docker, NGINX, and Node.js

Designing a Scalable Microservices Architecture With Docker, NGINX, and Node.js

Building monoliths may be quicker for small apps, but scaling them can become a nightmare. Microservices break down your application into independent services that can scale and deploy separately. In this guide, we’ll walk through setting up a basic microservices architecture using Docker, NGINX as a reverse proxy, and Node.js services.

Architecture Overview

We’ll build two simple Node.js services: user-service and product-service. NGINX will route requests to the correct service, and Docker Compose will tie everything together.

Step 1: Create the Project Structure

microservices-app/
├── nginx/
│   └── default.conf
├── user-service/
│   └── index.js
├── product-service/
│   └── index.js
├── docker-compose.yml

Step 2: Create Node Services

// user-service/index.js
const express = require('express');
const app = express();
app.get('/users', (req, res) => res.json([{ id: 1, name: 'Alice' }]));
app.listen(3001, () => console.log('User Service on port 3001'));
// product-service/index.js
const express = require('express');
const app = express();
app.get('/products', (req, res) => res.json([{ id: 101, name: 'Laptop' }]));
app.listen(3002, () => console.log('Product Service on port 3002'));

Step 3: Add Dockerfiles

# Dockerfile for both services
FROM node:18
WORKDIR /app
COPY . .
RUN npm install express
CMD ["node", "index.js"]

Step 4: Configure NGINX

# nginx/default.conf
server {
  listen 80;

  location /users {
    proxy_pass http://user-service:3001;
  }

  location /products {
    proxy_pass http://product-service:3002;
  }
}

Step 5: Compose Everything With Docker

# docker-compose.yml
version: '3'
services:
  user-service:
    build: ./user-service
    ports:
      - "3001:3001"

  product-service:
    build: ./product-service
    ports:
      - "3002:3002"

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - user-service
      - product-service

Step 6: Test Your Microservices

Start the services with:

docker-compose up --build

Then visit:

  • http://localhost/users → forwarded to user-service
  • http://localhost/products → forwarded to product-service

Conclusion

This setup forms the foundation of a scalable microservices architecture. You can expand this by adding service discovery, authentication, logging, and container orchestration with Kubernetes. Microservices bring complexity, but when done right, they offer unmatched flexibility and scalability.

If this post helped you, consider supporting me: buymeacoffee.com/hexshift