Operations 10 min read

Deploying Node.js Microservices with Docker and Docker Compose

This article demonstrates how to package a NestJS-based microservice architecture into Docker images, build and run them individually, and orchestrate multiple services using Docker Compose, covering Dockerfile multi-stage builds, port mapping, IP binding, and practical deployment steps for Node.js backend services.

IT Services Circle
IT Services Circle
IT Services Circle
Deploying Node.js Microservices with Docker and Docker Compose

The backend business logic of a NestJS project is split into separate microservices that communicate via TCP, with a main HTTP service forwarding requests to them. After development, the services are built with npm run build and the resulting dist folder is deployed.

Instead of copying files manually, each service is containerized using Docker. A typical multi‑stage Dockerfile for the main service looks like this:

FROM node:alpine as development<br/>WORKDIR /usr/app<br/>COPY package.json ./<br/>RUN npm install<br/>COPY . .<br/>RUN npm run build<br/>FROM node:alpine as production<br/>WORKDIR /usr/app<br/>COPY package.json ./<br/>RUN npm install --only=production<br/>COPY . .<br/>COPY --from=development /usr/app/dist ./dist<br/>CMD ["node", "dist/main.js"]

Each microservice has a similar Dockerfile. After building the images with docker build -t main-app ., docker build -t ms-calc . and docker build -t ms-log ., they can be started individually with docker run -p 3000:3000 main-app, docker run -p 8888:8888 ms-calc and docker run -p 9999:9999 ms‑log. Port mapping ( -p host:container) and binding the services to 0.0.0.0 are essential so the containers are reachable from the host.

Running several containers manually is cumbersome, especially when the number of services grows. Docker Compose solves this by defining all services, their build contexts, Dockerfiles, ports, and start‑up order in a single docker-compose.yml file:

services:<br/>  main-app:<br/>    build:<br/>      context: ./main-app<br/>      dockerfile: ./Dockerfile<br/>    depends_on:<br/>      - ms-calc<br/>      - ms-log<br/>      - rabbitmq<br/>    ports:<br/>      - '3000:3000'<br/>  ms-calc:<br/>    build:<br/>      context: ./micro-service-calc<br/>      dockerfile: ./Dockerfile<br/>    ports:<br/>      - '8888:8888'<br/>  ms-log:<br/>    build:<br/>      context: ./micro-service-log<br/>      dockerfile: ./Dockerfile<br/>    ports:<br/>      - '9999:9999'<br/>  rabbitmq:<br/>    image: rabbitmq<br/>    ports:<br/>      - '5672:5672'

Running docker-compose up builds all images and starts the containers in the correct order, merging their logs for easier monitoring. The setup can be managed via Docker Desktop, which shows the images and running containers.

Key points include using multi‑stage builds to keep production images small, copying only the dist folder to the final image, binding services to 0.0.0.0 instead of localhost, and using the host’s IP when services need to call each other. This workflow provides a reproducible, scalable way to deploy Node.js backend microservices.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DockerMicroservicesDevOps
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.