LoginSignup
6
6

More than 1 year has passed since last update.

Dockerで始めるgRPC

Last updated at Posted at 2022-12-31

はじめに

dockerを使ったgrpcをまとめたいと思います。
内容は、クイックスタートに準拠しています。

レポジトリーを作りました。

gRPCとは

gRPCとは、http2とバイナリを使用した高速通信可能なgoogleが開発したPRCフレームワークです。

Qiita

プロトコルバッファとは

構造化データ定義し、シリアライズするためのオープンソースメカニズムです。
protocコマンドを打つことで、goファイルを自動生成します。

コーディング

Dockerをbuild

ファイル構成
.
├── client
│   ├── Dockerfile
│   └── go_grpc
│       └── bin
│           └── go_starter
├── docker-compose.yml
└── server
    ├── Dockerfile
    └── go_grpc
        └── bin
            └── go_starter
Dockerfile
FROM golang:1.19-buster

ENV PROTOBUF_VERSION 3.17.3

RUN apt-get update \
    && apt-get install -y protobuf-compiler unzip --no-install-recommends \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /practice-grpc
COPY . /practice-grpc

## build時のみ使いたいので、runで実行。
RUN chmod +x go_grpc/bin/go_starter && go_grpc/bin/go_starter

RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
docker-compose.yml
version: '3.7'

services:
  server:
    build: ./server
    container_name: "server-grpc"
    volumes:
      - ./server:/practice-grpc
    ports:
      - "8080:8080"
    tty: true
  client:
    build: ./client
    container_name: "client-grpc"
    volumes:
      - ./client:/practice-grpc
    tty: true

go mod initコマンドも合わせて行っています。

go_grpc/bin/go_starter
#!/usr/bin/env bash

set -euo pipefail

function exits() {
  local cwd="$1"
  local File="${cwd}/go.mod"
  local c_dir=${cwd##*/}

  if [ -f "${File}" ]; then
    echo "${File} exist"
  else
    cd "${c_dir}"
    go mod init "${c_dir}"
  fi
}

function main() {
  local cwd
  cwd="$(cd "$(dirname "$0")/.." && pwd)"
  exits "${cwd}"
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  main "$@"
fi

buildします。

docker compose up

ここまでで、初期設定は終わりです。

protoコマンドを実行

ディレクトリーとファイルを作ります。

mkdir server/go_grpc/pb server/go_grpc/proto
touch server/go_grpc/proto/route_guide.proto
server/go_grpc/proto/Helloworld.proto
syntax = "proto3";

package helloworld;

option go_package = "./pb"; // 自動生成されるgoファイルの出力先を指定します。

// サービスメソッドで使用されるすべてのリクエスト
// およびレスポンスタイプのプロトコルバッファメッセージタイプ定義

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

protoc -I. --go_out=. --go-grpc_out=. proto/*.proto

-Iは起点になっているディレクトリを表しています。.はカレントディレクトリ。
--go_outはgoファイルに変換することを意味しています。

pb/helloworld.pb.go
pb/helloworld_grpc.pb.go
の二つができました。

同じことをclient側でもします。

server側

server側もclient側も見やすくするために書き直しました。

server/main.go
package main

import (
	"context"
	"log"
	"net"

	pb "go_grpc/pb"
	"google.golang.org/grpc"
)

type server struct {
	pb.UnimplementedGreeterServer
}

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() {
	lis, err := net.Listen("tcp", "server:8080")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

client側

client/main.go
package main

import (
	"context"
	"log"
	"time"

	pb "go_grpc/pb"

	grpc "google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	conn, err := grpc.Dial("server:8080", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "yuki"})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}

通信

準備が整ったので、実際に通信をしてみます。

最終的なファイル構成
.
├── client
│   ├── Dockerfile
│   └── go_grpc
│       ├── bin
│       │   └── go_starter
│       ├── client
│       │   └── main.go
│       ├── go.mod
│       ├── go.sum
│       ├── pb
│       │   ├── Helloworld.pb.go
│       │   └── Helloworld_grpc.pb.go
│       └── proto
│           └── Helloworld.proto
├── docker-compose.yml
└── server
    ├── Dockerfile
    └── go_grpc
        ├── bin
        │   └── go_starter
        ├── go.mod
        ├── go.sum
        ├── pb
        │   ├── Helloworld.pb.go
        │   └── Helloworld_grpc.pb.go
        ├── proto
        │   └── Helloworld.proto
        └── server
            └── main.go

server-grpcコンテナ内に入り以下のコマンドを実行します。

cd go_grpc
go run server/main.go
server
2022/12/31 05:25:49 server listening at 172.18.0.3:8080
2022/12/31 05:25:55 Received: yuki

client-grpcコンテナ内に入り以下のコマンドを実行します。

cd go_grpc
go run client/main.go
client
2022/12/31 05:25:58 Greeting: Hello yuki

期待通りの動きをしています。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6