typescriptdockernestjsgrpcgrpc-node

nestjs grpc client cannot resolve dns to grpc service inside docker container


I have a grpc service and a simple http server serving as a grpc client. They work fine when running locally. However, once put inside separate docker containers, they cannot establish a connection. The grpc service runs and exposes port :5001.

Registering the grpc service in nestjs grpc client app

  ClientsModule.register([
      {
        name: "TOKEN_NAME",
        transport: Transport.GRPC,
        options: {
           ...GRPC_OPTIONS,
           url: process.env.GRPC_SERVICE_URL
        },
      },
    ]),

I've tried using container name as URL:

version: '3.9'
services:
  grpc-service:
    restart: always
    build: ./grpc-service
    container_name: grpc-service
  grpc-client:
    restart: always
    build: ./backend
    container_name: grpc-client
#    links:
#      - "grpc-service:service"
    depends_on:
      - grpc-service
    ports:
      - "3000:3000"
    environment:
      - GRPC_SERVICE_URL=http://grpc-service:5001
#     - GRPC_SERVICE_URL=http://service:5001

and also tried creating a network and assigning IP addresses:

version: '3.9'
networks:
  mynetwork:
    driver: bridge
    ipam:
      config:
        - subnet: 179.20.0.0/24

services:
  grpc-service:
    restart: always
    build: ./grpc-service
    container_name: grpc-service
    networks:
      mynetwork:
        ipv4_address: 179.20.0.5
  grpc-client:
    restart: always
    build: ./backend
    container_name: grpc-client
    networks:
      mynetwork:
        ipv4_address: 179.20.0.6

    depends_on:
      - grpc-service
    ports:
      - "3000:3000"
    environment:
      - GRPC_SERVICE_URL=179.20.0.5:5001

Errors:

Using http://grpc-service:5001

grpc-client       | [Nest] 1  - 09/20/2022, 12:20:14 PM   ERROR [ExceptionsHandler] 14 UNAVAILABLE: Name resolution failed for target dns:http://grpc-service:5001
grpc-client       | Error: 14 UNAVAILABLE: Name resolution failed for target dns:http://grpc-service:5001
grpc-client       |     at Object.callErrorFromStatus (/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
grpc-client       |     at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client.js:190:52)
grpc-client       |     at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
grpc-client       |     at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
grpc-client       |     at /node_modules/@grpc/grpc-js/build/src/call-stream.js:188:78
grpc-client       |     at processTicksAndRejections (node:internal/process/task_queues:78:11)
grpc-client       | for call at
grpc-client       |     at ServiceClientImpl.makeUnaryRequest (/node_modules/@grpc/grpc-js/build/src/client.js:160:30)
grpc-client       |     at ServiceClientImpl.<anonymous> (/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
grpc-client       |     at Observable._subscribe (/node_modules/@nestjs/microservices/client/client-grpc.js:177:35)
grpc-client       |     at Observable._trySubscribe (/node_modules/rxjs/dist/cjs/internal/Observable.js:41:25)
grpc-client       |     at /node_modules/rxjs/dist/cjs/internal/Observable.js:35:31
grpc-client       |     at Object.errorContext (/node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)
grpc-client       |     at Observable.subscribe (/node_modules/rxjs/dist/cjs/internal/Observable.js:26:24)
grpc-client       |     at /node_modules/rxjs/dist/cjs/internal/lastValueFrom.js:10:16
grpc-client       |     at new Promise (<anonymous>)
grpc-client       |     at lastValueFrom (/node_modules/rxjs/dist/cjs/internal/lastValueFrom.js:7:12)

Using 179.20.0.5:5001

grpc-client       | [Nest] 1  - 09/20/2022, 12:22:14 PM   ERROR [ExceptionsHandler] 14 UNAVAILABLE: No connection established
grpc-client       | Error: 14 UNAVAILABLE: No connection established
grpc-client       |     at Object.callErrorFromStatus (/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
grpc-client       |     at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client.js:190:52)
grpc-client       |     at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
grpc-client       |     at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
grpc-client       |     at /node_modules/@grpc/grpc-js/build/src/call-stream.js:188:78
grpc-client       |     at processTicksAndRejections (node:internal/process/task_queues:78:11)
grpc-client       | for call at
grpc-client       |     at ServiceClientImpl.makeUnaryRequest (/node_modules/@grpc/grpc-js/build/src/client.js:160:30)
grpc-client       |     at ServiceClientImpl.<anonymous> (/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
grpc-client       |     at Observable._subscribe (/node_modules/@nestjs/microservices/client/client-grpc.js:177:35)
grpc-client       |     at Observable._trySubscribe (/node_modules/rxjs/dist/cjs/internal/Observable.js:41:25)
grpc-client       |     at /node_modules/rxjs/dist/cjs/internal/Observable.js:35:31
grpc-client       |     at Object.errorContext (/node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)
grpc-client       |     at Observable.subscribe (/node_modules/rxjs/dist/cjs/internal/Observable.js:26:24)
grpc-client       |     at /node_modules/rxjs/dist/cjs/internal/lastValueFrom.js:10:16
grpc-client       |     at new Promise (<anonymous>)
grpc-client       |     at lastValueFrom (/node_modules/rxjs/dist/cjs/internal/lastValueFrom.js:7:12)

EDIT

I have also tried running the grpc service inside docker with port mapping 5001:5001 with http client ran locally attempting to connect with the grpc service on localhost:5001. In this case I get connection dropped error

  [Nest] 93680  - 09/24/2022, 2:52:50 PM   ERROR [ExceptionsHandler] 14 UNAVAILABLE: Connection dropped
Error: 14 UNAVAILABLE: Connection dropped
         at Object.callErrorFromStatus (/Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/call.ts:81:17)
         at Object.onReceiveStatus (/Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/client.ts:352:36)
         at Object.onReceiveStatus (/Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/client-interceptors.ts:462:34)
         at Object.onReceiveStatus (/Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/client-interceptors.ts:424:48)
         at /Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/call-stream.ts:330:24
         at processTicksAndRejections (node:internal/process/task_queues:78:11)
  for call at
  at ServiceClientImpl.makeUnaryRequest (/Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/client.ts:324:26)
  at ServiceClientImpl.<anonymous> (/Users/grpc-docker/backend/node_modules/@grpc/grpc-js/src/make-client.ts:189:15)
  at Observable._subscribe (/Users/grpc-docker/backend/node_modules/@nestjs/microservices/client/client-grpc.js:177:35)
  at Observable._trySubscribe (/Users/grpc-docker/backend/node_modules/rxjs/src/internal/Observable.ts:245:19)
  at /Users/grpc-docker/backend/node_modules/rxjs/src/internal/Observable.ts:235:18
  at Object.errorContext (/Users/grpc-docker/backend/node_modules/rxjs/src/internal/util/errorContext.ts:29:5)
  at Observable.subscribe (/Users/grpc-docker/backend/node_modules/rxjs/src/internal/Observable.ts:221:5)
  at /Users/grpc-docker/backend/node_modules/rxjs/src/internal/lastValueFrom.ts:59:12
  at new Promise (<anonymous>)
  at lastValueFrom (/Users/grpc-docker/backend/node_modules/rxjs/src/internal/lastValueFrom.ts:56:10)

Solution

  • Basically, the issue was with how the grpc service was being started.

    Nestjs's createMicroservice method accepts grpc options, one of which is a url. Mine was set to localhost:5001, however, apparently that does not make it accessible from outside the container. After changing it to 0.0.0.0:5001 there was no more issues establishing a connection. After figuring this out I've found a stack exchange thread explaining it in more detail.