Container orchestration
Learn container orchestration with Docker Compose and Kubernetes for microservices deployment. This is a foundational concept in server-side JavaScript development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world Node.js experience. Take your time with each section and practice the examples
Docker Compose for Microservices
Docker Compose allows you to define and run multi-container applications. It's perfect for local development and testing of microservices architecture.. This is an essential concept that every Node.js developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Docker Compose Configuration
# docker-compose.yml
version: '3.8'
services:
# API Gateway
api-gateway:
build: ./api-gateway
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- USERS_SERVICE_URL=http://users-service:3001
- ORDERS_SERVICE_URL=http://orders-service:3002
- PRODUCTS_SERVICE_URL=http://products-service:3003
- PAYMENTS_SERVICE_URL=http://payments-service:3004
depends_on:
- users-service
- orders-service
- products-service
- payments-service
networks:
- microservices-network
# Users Service
users-service:
build: ./users-service
ports:
- "3001:3001"
environment:
- NODE_ENV=development
- MONGODB_URI=mongodb://users-db:27017/users
- JWT_SECRET=your-secret-key
depends_on:
- users-db
networks:
- microservices-network
# Orders Service
orders-service:
build: ./orders-service
ports:
- "3002:3002"
environment:
- NODE_ENV=development
- MONGODB_URI=mongodb://orders-db:27017/orders
- USERS_SERVICE_URL=http://users-service:3001
- RABBITMQ_URL=amqp://rabbitmq:5672
depends_on:
- orders-db
- rabbitmq
networks:
- microservices-network
# Products Service
products-service:
build: ./products-service
ports:
- "3003:3003"
environment:
- NODE_ENV=development
- MONGODB_URI=mongodb://products-db:27017/products
depends_on:
- products-db
networks:
- microservices-network
# Payments Service
payments-service:
build: ./payments-service
ports:
- "3004:3004"
environment:
- NODE_ENV=development
- MONGODB_URI=mongodb://payments-db:27017/payments
- STRIPE_SECRET_KEY=your-stripe-secret-key
depends_on:
- payments-db
networks:
- microservices-network
# Databases
users-db:
image: mongo:5.0
ports:
- "27017:27017"
volumes:
- users-data:/data/db
networks:
- microservices-network
orders-db:
image: mongo:5.0
ports:
- "27018:27017"
volumes:
- orders-data:/data/db
networks:
- microservices-network
products-db:
image: mongo:5.0
ports:
- "27019:27017"
volumes:
- products-data:/data/db
networks:
- microservices-network
payments-db:
image: mongo:5.0
ports:
- "27020:27017"
volumes:
- payments-data:/data/db
networks:
- microservices-network
# Message Queue
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"
environment:
- RABBITMQ_DEFAULT_USER=admin
- RABBITMQ_DEFAULT_PASS=admin
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- microservices-network
# Monitoring
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- microservices-network
grafana:
image: grafana/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
networks:
- microservices-network
volumes:
users-data:
orders-data:
products-data:
payments-data:
rabbitmq-data:
grafana-data:
networks:
microservices-network:
driver: bridge
# Dockerfile for each service
# users-service/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3001
CMD ["npm", "start"]
# orders-service/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3002
CMD ["npm", "start"]
# products-service/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3003
CMD ["npm", "start"]
# payments-service/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3004
CMD ["npm", "start"]
# api-gateway/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]Kubernetes Deployment
# Kubernetes manifests for microservices
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: microservices
---
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: microservices-config
namespace: microservices
data:
NODE_ENV: "production"
JWT_SECRET: "your-secret-key"
STRIPE_SECRET_KEY: "your-stripe-secret-key"
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: microservices-secrets
namespace: microservices
type: Opaque
data:
mongodb-uri: bW9uZ29kYjovL21vbmdvZGItc2VydmljZToyNzAxNy8= # base64 encoded
rabbitmq-url: YW1xcDovL3JhYmJpdG1xOjU2NzI= # base64 encoded
---
# users-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: users-service
namespace: microservices
spec:
replicas: 3
selector:
matchLabels:
app: users-service
template:
metadata:
labels:
app: users-service
spec:
containers:
- name: users-service
image: your-registry/users-service:latest
ports:
- containerPort: 3001
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: microservices-config
key: NODE_ENV
- name: JWT_SECRET
valueFrom:
configMapKeyRef:
name: microservices-config
key: JWT_SECRET
- name: MONGODB_URI
valueFrom:
secretKeyRef:
name: microservices-secrets
key: mongodb-uri
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 5
periodSeconds: 5
---
# users-service-service.yaml
apiVersion: v1
kind: Service
metadata:
name: users-service
namespace: microservices
spec:
selector:
app: users-service
ports:
- protocol: TCP
port: 3001
targetPort: 3001
type: ClusterIP
---
# orders-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: orders-service
namespace: microservices
spec:
replicas: 3
selector:
matchLabels:
app: orders-service
template:
metadata:
labels:
app: orders-service
spec:
containers:
- name: orders-service
image: your-registry/orders-service:latest
ports:
- containerPort: 3002
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: microservices-config
key: NODE_ENV
- name: MONGODB_URI
valueFrom:
secretKeyRef:
name: microservices-secrets
key: mongodb-uri
- name: RABBITMQ_URL
valueFrom:
secretKeyRef:
name: microservices-secrets
key: rabbitmq-url
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
---
# api-gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
namespace: microservices
spec:
replicas: 2
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
spec:
containers:
- name: api-gateway
image: your-registry/api-gateway:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
valueFrom:
configMapKeyRef:
name: microservices-config
key: NODE_ENV
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
---
# api-gateway-service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-gateway
namespace: microservices
spec:
selector:
app: api-gateway
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservices-ingress
namespace: microservices
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: api.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-gateway
port:
number: 80
---
# horizontal-pod-autoscaler.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: users-service-hpa
namespace: microservices
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: users-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80