无法连接到在本地 Docker 容器中运行的 Go GRPC 服务器。
无法连接到在本地 Docker 容器中运行的 Go GRPC 服务器。
我有一个go grpc服务。我在mac上开发,版本是sierra。当在本地运行grpc客户端与服务进行通信时,一切都正常,但是当在docker容器中运行相同的客户端与相同的服务进行通信时,我会得到以下错误:
transport: http2Client.notifyError被通知客户端传输已被中断EOF。
FATA[0000] rpc错误: code = Internal desc = 传输正在关闭
这是我的docker文件:
FROM golang:1.7.5 RUN mkdir -p /go/src/github.com/foo/bar WORKDIR /go/src/github.com/foo/bar COPY . /go/src/github.com/foo/bar # ONBUILD RUN go-wrapper download RUN go install ENTRYPOINT /go/bin/bar EXPOSE 51672
构建镜像的命令是:
docker build -t bar .
启动docker容器的命令是:
docker run -p 51672:51672 --name bar-container bar
其他信息:
- 从docker容器内部运行的客户端程序正常
- 连接到常规的rest端点正常工作(http2,grpc相关?)
- 在OS X中运行
lsof
命令会得到以下结果$lsof -i | grep 51672 com.docke 984 oldDave 21u IPv4 0x72779547e3a32c89 0t0 TCP *:51672 (LISTEN) com.docke 984 oldDave 22u IPv6 0x72779547cc0fd161 0t0 TCP localhost:51672 (LISTEN)
- 这是我的服务器代码片段:
server := &Server{}
endpoint := "localhost:51672"
lis, err := net.Listen("tcp", endpoint)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(grpc.Creds(creds))
pb.RegisterExpServiceServer(s, server)
// 在gRPC服务器上注册反射服务。
reflection.Register(s)
log.Info("Starting Exp server: ", endpoint)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
无法连接到在本地Docker容器中运行的Go GRPC服务器的问题出现的原因是服务器只监听了localhost地址(127.0.0.1),而在Docker容器中,127.0.0.1是容器内部的回环地址,无法从容器外部访问。当通过"-p 51672:51672"参数启动Docker容器时,流向127.0.0.1:51672的流量会被转发到容器的IP地址(例如172.17.0.2),但由于容器内没有在172.17.0.2:51672上监听,连接尝试会失败。为了解决这个问题,需要将服务器的监听地址修改为":51672",这样服务器就会监听容器内的所有IP地址。另外,如果使用Docker Compose运行容器,可以使用在yaml文件中指定的容器名称作为主机名,它会自动映射到正确的IP地址。
补充信息:当在Docker容器中暴露端口时,Docker会创建iptables规则来进行实际的转发。可以使用命令"iptables -n -L"和"iptables -t nat -n -L"查看这些规则。另外,将监听地址设置为":[端口号]"在nodejs的grpc实现中不起作用,会出现错误"getaddrinfo failed"。
感谢以上回答的提供者,他们的解答帮助了许多人解决了类似的问题。
无法连接到在本地Docker容器中运行的Go GRPC服务器
问题原因:Docker容器中的网络配置不正确。
解决方法:在Docker容器中定义网络,并将该网络的IP地址分配给你的IP地址(例如:178.20.0.5)。
具体步骤如下:
1. 在Docker容器中定义网络。可以使用以下命令创建一个新的网络:
docker network create mynetwork
2. 运行Go GRPC服务器的Docker容器时,将该容器连接到刚刚创建的网络。可以使用以下命令启动容器:
docker run --network=mynetwork mygrpcserver
请注意,将"mynetwork"替换为你所创建的网络的名称,"mygrpcserver"替换为你的Go GRPC服务器的Docker镜像名称。
3. 确定Go GRPC服务器容器的IP地址。可以使用以下命令查看容器的IP地址:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
请将"
4. 将Go GRPC服务器容器的IP地址分配给你的IP地址。可以在代码中使用以下方法分配IP地址:
import (
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", "
if err != nil {
fmt.Println("Failed to connect:", err)
os.Exit(1)
}
// 继续处理连接
}
请将"
通过按照上述步骤进行操作,你应该能够成功连接到在本地Docker容器中运行的Go GRPC服务器。