Reputation: 1182
I'm implementing two services (server and client) running on two different containers and trying to use gRPC to communicate between them.
If I deploy the server as a container and run the client not on a container, everything works just fine. But if I deploy the client on a different container I get Error #01: could not retrieve restaurant's list: rpc error: code = Unavailable desc = grpc: the connection is unavailable
error.
What steps am I missing to communicate two different containers using gRPC?
PS: I would like to try without Kubernetes for now.
SERVER
func Serve() {
log.Println("serving...")
port := ":50051"
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen on port %s: %v", port, err)
}
s := grpc.NewServer()
server := server{}
RegisterNeo4BaconServer(s, server)
if err := s.Serve(lis); err != nil {
log.Fatal("could not serve: ", err)
}
}
Makefile
image: ## build docker image and push image to registry
@docker build -t neo4bacon -f resources/prod/Dockerfile .
run: ## deploy application container
@docker run --rm -d --name neo4bacon neo4bacon
CLIENT
func Get() (*api.RestaurantList, error) {
// Neo4bacon backend
backendPort := ":50051"
conn, err := grpc.Dial(backendPort, grpc.WithInsecure())
if err != nil {
&api.RestaurantList{}, fmt.Errorf("could not connect to backend %s: %s", backendPort, err)
}
defer conn.Close()
client := api.NewNeo4BaconClient(conn)
restaurantList, err := client.List(context.Background(), &api.Empty{})
if err != nil {
return &api.RestaurantList{}, fmt.Errorf("could not retrieve restaurant's list: %s", err)
}
return restaurantList, nil
}
Makefile
image: ## build docker image and push image to registry
@docker build -t alesr/bacon-api -f resources/prod/Dockerfile .
run: ## deploy docker container
@docker run --rm -d -p 8080:8080 --name bacon-api bacon-api
Upvotes: 3
Views: 12390
Reputation: 671
If your gRPC client and server are hosted on docker, to establish the connection between to container you should follow the below steps.
First, you should create a docker network.
docker network create web_server --driver bridge
Then register your containers with the created network. You should mention the service name and the network in the docker run command.
docker run -dit -p 3000:3000 --name question-service --network web_server ${{ env.REGISTRY }}/question-service:latest
Now your URL should format as below,
{{service-name}}:port
as an example
question-service:3000
for more details, you can refer to this blog
Upvotes: 0
Reputation: 265045
You need to include the hostname in the dial function, otherwise it's looking at localhost which is unique to each container (docker creates a separate networking namespace for containers by default). Change the following:
backendPort := "neo4bacon:50051"
Edit: you also need to setup a network and connect the containers to that network because the default bridge does not include DNS discovery:
docker network create baconnet
docker run --rm -d --net baconnet --name neo4bacon neo4bacon
docker run --rm -d --net baconnet -p 8080:8080 --name bacon-api bacon-api
Upvotes: 10