I have a deployed nest.js gRPC server and a client in docker containers with the following docker commands,
Client (api-gateway) :
docker run -dit -p 3000:3000 --hostname ${{ env.IMAGE_NAME }} --name ${{ env.IMAGE_NAME }} --network web_server ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{env.TAG}}
env for client
IMAGE_NAME=api-gateway
Server (question-service) :
docker run -dit -p 40000:40000 --hostname ${{ env.IMAGE_NAME }} --name ${{ env.IMAGE_NAME }} --network web_server ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{env.TAG}}
env for server
IMAGE_NAME=question-service
Main.ts of the server (question-service) is like this,
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '@nestjs/microservices';
import { join } from 'path';
const microserviceOptions = {
transport: Transport.GRPC,
options: {
package: 'questionPackage',
protoPath: join(__dirname, '../src/question/question.proto'),
url: '0.0.0.0:40000',
},
};
async function bootstrap() {
const app = await NestFactory.createMicroservice(
AppModule,
microserviceOptions,
);
app.listen();
}
bootstrap();
and the client integration is like this,
grpc.option.ts:
import { ClientOptions, Transport } from '@nestjs/microservices';
import { join } from 'path';
export const microserviceOptions: ClientOptions = {
transport: Transport.GRPC,
options: {
package: 'questionPackage',
protoPath: join(__dirname, '../question/question.proto'),
url: 'question-service:40000',
},
};
question.service.ts:
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Client, ClientGrpc } from '@nestjs/microservices';
import { CreateQuestionInput } from './dto/create-question.input';
import { QuestionGrpcService } from './grpc.interface';
import { microserviceOptions } from './grpc.option';
import { Question } from './entities/question.entity';
import { firstValueFrom } from 'rxjs';
@Injectable()
export class QuestionService implements OnModuleInit {
private logger = new Logger('QuestionService');
@Client(microserviceOptions)
private client: ClientGrpc;
private questionGrpcService: QuestionGrpcService;
onModuleInit() {
this.questionGrpcService =
this.client.getService<QuestionGrpcService>('QuestionService');
}
createQuestion(createQuestionInput: CreateQuestionInput) {
return this.questionGrpcService.createQuestion(createQuestionInput);
}
async getQuestions(): Promise<Question[]> {
let questions = [];
const res = await firstValueFrom(this.questionGrpcService.getQuestions({}));
questions = res.questionsResposes;
return questions;
}
}
But when I call the graphql enpoint of api-gateway to get all question it returns following error,
{
"errors": [
{
"message": "14 UNAVAILABLE: Name resolution failed for target dns:http://question-service:40000",
"locations": [
{
"line": 16,
"column": 3
}
],
"path": [
"question"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"code": 14,
"details": "Name resolution failed for target dns:http://question-service:40000",
"metadata": {},
"stacktrace": [
"Error: 14 UNAVAILABLE: Name resolution failed for target dns:http://question-service:40000",
" at Object.callErrorFromStatus (/node_modules/@grpc/grpc-js/build/src/call.js:31:19)",
" at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client.js:190:52)",
" at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)",
" at Object.onReceiveStatus (/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)",
" at /node_modules/@grpc/grpc-js/build/src/call-stream.js:188:78",
" at processTicksAndRejections (internal/process/task_queues.js:79:11)",
"for call at",
" at ServiceClientImpl.makeUnaryRequest (/node_modules/@grpc/grpc-js/build/src/client.js:160:30)",
" at ServiceClientImpl.getQuestions (/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)",
" at Observable._subscribe (/node_modules/@nestjs/microservices/client/client-grpc.js:177:39)",
" at Observable._trySubscribe (/node_modules/rxjs/dist/cjs/internal/Observable.js:41:25)",
" at /node_modules/rxjs/dist/cjs/internal/Observable.js:35:31",
" at Object.errorContext (/node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)",
" at Observable.subscribe (/node_modules/rxjs/dist/cjs/internal/Observable.js:26:24)",
" at /node_modules/rxjs/dist/cjs/internal/firstValueFrom.js:24:16",
" at new Promise (<anonymous>)",
" at firstValueFrom (/node_modules/rxjs/dist/cjs/internal/firstValueFrom.js:8:12)"
]
}
}
}
],
"data": null
}
below command return,
sudo docker inspect web_server
[
{
"Name": "web_server",
"Id": "23b4a40928a88861f7a063db4dac5c491db5384181d28ee5563db52f96c22e55",
"Created": "2022-09-06T17:55:54.611611429Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"181868f91a188056e5f21de4bb6ca16b92f36befcd832386206256701b7be16a": {
"Name": "question-service",
"EndpointID": "01a4c375b95be1eb9be58993abcb8bf15fe2a8d91ac2635c4a3746036fc51747",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"828c06298e42184665507f3c6bd73a54feb36e3da3214360a015ba67104f1fdd": {
"Name": "api-gateway",
"EndpointID": "2ca0ba9b3f6664095e8146b5d6243362fc0a5188a73c80b7afd47207a5c62e1e",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
2
Answers
I was able to fix this issue by changing the URLs in both client and server configurations as below.
refer this anwer for more information. Also you can refer this blog post
I got this error for
eventstoredb
when running a container with entrypointdumb-init
. I also triedtini
and got the same error.This caused the error
ENTRYPOINT ["dumb-init", "node", "./dist/index.js"]
this also
ENTRYPOINT ["/sbin/tini","--", "node", "./dist/index.js"]
But this works
ENTRYPOINT ["node", "./dist/index.js"]