Microservices Communication in Docker

Once microservices are up and running, they need to communicate reliably. Docker provides built-in networking to enable seamless interaction between services across containers.


REST APIs vs. gRPC for Microservices Communication

Services communicate over HTTP using either REST or gRPC:

  • REST is widely adopted and easy to implement using HTTP and JSON.
  • gRPC is faster and more efficient, using HTTP/2 and Protocol Buffers — great for internal microservices.

For simplicity, this guide uses REST in examples.

Using Docker Networking

Docker Compose automatically creates a default network where services can discover each other by name. For example, user-service can call order-service using its container name as the hostname.

const axios = require('axios');

axios.get('http://order-service:5001/api/orders')
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

No IP address is needed — just the service name from docker-compose.yml.

Configuring Internal & External Networking

Docker Compose allows defining custom networks for better control. Example:

networks:
  backend:
    driver: bridge

services:
  user-service:
    build: ./user-service
    networks:
      - backend
  order-service:
    build: ./order-service
    networks:
      - backend

This allows isolation of backend services from frontend or external networks.

Example: Connecting user-service to order-service

Imagine user-service needs to retrieve all orders for a user from order-service:

// In user-service
GET /api/users/:id/orders

// user-service makes internal call:
axios.get(`http://order-service:5001/api/orders/user/${userId}`)

Internally, the services use Docker’s DNS to resolve container names automatically.

Docker Compose makes service communication easy using built-in DNS-based discovery. In the next section, we’ll look at managing data with Docker volumes and databases for each service.