Asuha
Asuha

Reputation: 261

My gRPC client in a docker container doesn't work but the client outside the container go well

Envs

$ protoc --version
libprotoc 3.7.1

$ docker-compose --version
docker-compose version 1.22.0, build f46880fe

$ docker --version
Docker version 20.10.0-beta1, build ac365d7

What I want to do

I want to make a microservice implemented by gin-gonic.

Codes

$ tree
.
├── api
│   ├── Dockerfile
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
│   ├── pb
│   │   ├── proto
│   │   │   └── user.proto
│   │   ├── user_grpc.pb.go
│   │   └── user.pb.go
│   └── services
│       ├── README.md
│       └── user
│           ├── Dockerfile
│           ├── go.mod
│           ├── go.sum
│           ├── main.go
│           └── pb
│               ├── user_grpc.pb.go
│               └── user.pb.go
├── docker-compose.yml
├── make_pb.sh
└── README.md

As you can see I have 2 Dockerfile now.
Dockefile in api dir run gRPC client program.
Another Dockerfile in user dir run gRPC server program.

api/main.go

package main

import (
    "context"
    "log"
    "os"
    "time"

    pb "github.com/Asuha-a/URLShortener/api/pb"
    "google.golang.org/grpc"
)

const (
    address     = "localhost:50051"
    defaultName = "world"
)

func main() {
    hello()
    //r := gin.Default()
    //r.GET("", hello)
    //r.Run()
}

func hello() {
    log.Println(grpc.WithBlock())
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    client := pb.NewGreeterClient(conn)

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := client.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}

api/services/user/main.go

package main

import (
    "context"
    "log"
    "net"

    pb "github.com/Asuha-a/URLShortener/api/services/user/pb"
    "google.golang.org/grpc"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
    log.Println("now listening")
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

docker-compose.yml

version: '3'

services:
  gateway:
    build:
      context: ./api/
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    tty:
      true
    depends_on:
      - user
  user:
    build:
      context: ./api/services/user
      dockerfile: Dockerfile
    ports:
      - 50051:50051
    tty:
      true

Dockerfiles have the same codes.

FROM golang:latest

RUN mkdir /go/src/work
WORKDIR /go/src/work
ADD . /go/src/work

CMD go run main.go

What happened

When I run docker-compose up, grpc.Dial doesn't seem to work.

The log is here

$ docker-compose up              
Recreating urlshortener_user_1 ... done
Recreating urlshortener_gateway_1 ... done
Attaching to urlshortener_user_1, urlshortener_gateway_1
user_1     | go: downloading google.golang.org/grpc v1.33.1
user_1     | go: downloading google.golang.org/protobuf v1.25.0
user_1     | go: downloading github.com/golang/protobuf v1.4.3
gateway_1  | go: downloading google.golang.org/grpc v1.33.1
gateway_1  | go: downloading github.com/golang/protobuf v1.4.3
gateway_1  | go: downloading google.golang.org/protobuf v1.25.0
user_1     | go: downloading google.golang.org/genproto v0.0.0-20201028140639-c77dae4b0522
user_1     | go: downloading golang.org/x/net v0.0.0-20201029055024-942e2f445f3c
gateway_1  | go: downloading google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877
gateway_1  | go: downloading golang.org/x/net v0.0.0-20201027133719-8eef5233e2a1
gateway_1  | go: downloading golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c
user_1     | go: downloading golang.org/x/sys v0.0.0-20201029020603-3518587229cd
user_1     | go: downloading golang.org/x/text v0.3.4
gateway_1  | go: downloading golang.org/x/text v0.3.4
user_1     | 2020/10/29 08:29:42 now listening
gateway_1  | 2020/10/29 08:29:43 true

That is expected printed 'Greeting: Hello world'.

What I tried

When I run the server and client without the container, it was succeeded.

run client

$ go run main.go 
2020/10/29 17:37:17 true
2020/10/29 17:38:02 Greeting: Hello world

run server

$ go run main.go 
2020/10/29 17:38:00 now listening
2020/10/29 17:38:02 Received: world

When I run the server without a container and run the client with a container, it was failed.

run client

$ docker-compose up              
Recreating urlshortener_gateway_1 ... done
Attaching to urlshortener_gateway_1
gateway_1  | go: downloading google.golang.org/protobuf v1.25.0
gateway_1  | go: downloading github.com/golang/protobuf v1.4.3
gateway_1  | go: downloading google.golang.org/grpc v1.33.1
gateway_1  | go: downloading google.golang.org/genproto v0.0.0-20201026171402-d4b8fe4fd877
gateway_1  | go: downloading golang.org/x/net v0.0.0-20201027133719-8eef5233e2a1
gateway_1  | go: downloading golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c
gateway_1  | go: downloading golang.org/x/text v0.3.4
gateway_1  | 2020/10/29 08:40:47 true

run server

$ go run main.go
2020/10/29 17:40:19 now listening

When I run the server with the client and run the client without the container, it was succeeded.

run client

$ go run main.go 
2020/10/29 17:43:40 true
2020/10/29 17:43:41 Greeting: Hello world

run server

$ docker-compose up
Removing urlshortener_user_1
Recreating 42fb18da11cf_urlshortener_user_1 ... done
Attaching to urlshortener_user_1
user_1  | go: downloading google.golang.org/grpc v1.33.1
user_1  | go: downloading google.golang.org/protobuf v1.25.0
user_1  | go: downloading github.com/golang/protobuf v1.4.3
user_1  | go: downloading golang.org/x/net v0.0.0-20201029055024-942e2f445f3c
user_1  | go: downloading google.golang.org/genproto v0.0.0-20201028140639-c77dae4b0522
user_1  | go: downloading golang.org/x/sys v0.0.0-20201029020603-3518587229cd
user_1  | go: downloading golang.org/x/text v0.3.4
user_1  | 2020/10/29 08:43:41 now listening
user_1  | 2020/10/29 08:43:41 Received: world

What I want to know

Why did running the client in container fail?
How to fix it?

Upvotes: 0

Views: 3451

Answers (1)

Asuha
Asuha

Reputation: 261

The Issue is solved by this comment.

Localhost in the container is not the same as where the server is running. – Matt 14 mins ago

I fixed the api/main.go.

address = "localhost:50051" -> address = "user:50051"

Now it works.
The host name have to be container name specified in docker-compose.yml.

Upvotes: 4

Related Questions