J'ai un service go grpc. Je développe sur un mac, sierra. Lorsque vous exécutez un client grpc contre le service localement, tout va bien, mais lorsque vous exécutez le même client contre le même service dans le conteneur Docker, j'obtiens cette erreur:
transport: http2Client.notifyError got notified that the client transport was broken EOF.
FATA[0000] rpc error: code = Internal desc = transport is closing
voici mon fichier 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
ma commande pour construire l'image:
docker build -t bar .
ma commande pour lancer le conteneur docker:
docker run -p 51672:51672 --name bar-container bar
l'exécution de la commande lsof
dans OS X donne ces résultats
$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)
voici un extrait de mon code serveur:
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)
// Register reflection service on gRPC server.
reflection.Register(s)
log.Info("Starting Exp server: ", endpoint)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
Lorsque vous spécifiez un nom d'hôte ou une adresse IP pour écouter (dans ce cas localhost qui se résout en 127.0.0.1), votre serveur n'écoutera que sur cette adresse IP.
L'écoute sur localhost n'est pas un problème lorsque vous êtes en dehors d'un conteneur Docker. Si votre serveur n'écoute que sur 127.0.0.1:51672, votre client peut facilement s'y connecter car la connexion est également établie à partir de 127.0.0.1.
Lorsque vous exécutez votre serveur à l'intérieur d'un conteneur Docker, il n'écoutera que le 127.0.0.1:51672 comme auparavant. Le 127.0.0.1 est une adresse de bouclage locale et n'est pas accessible en dehors du conteneur.
Lorsque vous lancez le conteneur Docker avec "-p 51672: 51672", il transfère le titre du trafic vers 127.0.0.1:51672 vers l'adresse IP du conteneur, qui dans mon cas est 172.17.0.2.
Le conteneur obtient une adresse IP dans l'interface réseau docker0 (que vous pouvez voir avec la commande "ip addr ls")
Ainsi, lorsque votre trafic est transféré vers le conteneur le 172.17.0.2:51672, il n'y a rien à écouter et la tentative de connexion échoue.
Le correctif:
Le problème est avec le point de terminaison d'écoute:
endpoint := "localhost:51672"
Pour résoudre votre problème, changez-le en
endpoint := ":51672"
Cela fera que votre serveur écoutera toutes les adresses IP de son conteneur.
Informations supplémentaires:
Lorsque vous exposez des ports dans un conteneur Docker, Docker crée des règles iptables pour effectuer le transfert réel. Voir ceci . Vous pouvez afficher ces règles avec:
iptables -n -L
iptables -t nat -n -L