Go gRPC+Protocol Buffers on Ubuntu — マイクロサービス間通信の実装

開発環境

GoでgRPCとProtocol Buffersを使ったマイクロサービス間通信を、Ubuntu 24.04 世代の環境で実際にセットアップする方法を説明します。.proto ファイルの定義からコード生成、サーバー・クライアントの実装、そして実際に通信させてレスポンスを受け取るところまで、すべてDockerコンテナで動かして確認しました。

結論から言うと、golang:1.24 公式イメージ(Go 1.24.13)+ protobuf-compiler 3.21.12 + protoc-gen-go v1.34.2 + protoc-gen-go-grpc 1.4.0 の組み合わせで、.proto から生成したコードがそのままビルド・通信できることを実測で確認しています(2026-06-14 実測)。

本記事のコマンドと出力は、すべて docker run golang:1.24docker run ubuntu:24.04 の実行結果です。手順をそのまま再現できる形でまとめます。

この記事のポイント

  • apt install protobuf-compiler で protoc 3.21.12 が入る(Ubuntu 24.04・golang:1.24 とも同じ 3.21.12 系を実測)
  • Go 1.24 は公式イメージ golang:1.24 を使うのが最も確実(中身は Debian 13 trixie ベース・Go 1.24.13 同梱)
  • go installprotoc-gen-go v1.34.2protoc-gen-go-grpc 1.4.0 を追加する
  • protoc 1コマンドで *.pb.go(メッセージ)と *_grpc.pb.go(サービス)が自動生成される(実測で 221行+110行)
  • Ubuntu 22.04 は protoc 3.12.4・Go 1.18 と古い。新しい環境で組むなら 24.04 系を推奨

目次

  1. gRPC と Protocol Buffers とは
  2. 実行環境と前提条件
  3. ツールチェーンのインストール
  4. proto ファイルを定義する
  5. protoc でコードを生成する
  6. gRPC サーバーを実装する
  7. gRPC クライアントを実装する
  8. サーバーとクライアントを動かす
  9. Ubuntu 22.04 vs 24.04 パッケージ比較
  10. よくあるエラーと解決策
  11. まとめ

gRPC と Protocol Buffers とは

gRPC(gRPC Remote Procedure Calls)は、Google が開発したオープンソースの RPC フレームワークです。RPC とは、別のプロセスやサーバー上の関数をローカル関数のように呼び出す仕組みのことです。gRPC はマイクロサービス間の通信に広く使われており、HTTP/2 をベースにしているため多重化やストリーミングに対応しています。

Protocol Buffers(protobuf)はデータシリアライズ形式で、JSON より高速でコンパクトなバイナリ形式です。.proto ファイルにインターフェースを定義することで、サーバーとクライアント両方のスタブコードを自動生成できるのが最大の特徴です。

gRPC + Protocol Buffers 開発フロー(概念図)
gRPC + Protocol Buffers 開発フロー(概念図)

上の図のように、.proto ファイルを一度定義すれば、protoc コマンドで Go のコードが自動生成されます。手書きのシリアライズ/デシリアライズ処理は一切不要で、サーバー側は生成された関数を実装するだけ、クライアント側は生成された関数を呼ぶだけです。

実行環境と前提条件

今回はローカル環境を汚さないよう、すべて Docker 公式イメージの中で検証しました。実測した環境は次の通りです。

項目 バージョン 備考
Go 1.24.13 golang:1.24 公式イメージに同梱(2026-06-14 実測)
ベースOS(golang:1.24) Debian 13 (trixie) golang 公式イメージは Debian ベース。protoc は Ubuntu 24.04 と同じ 3.21.12 系
protobuf-compiler 3.21.12 apt install で取得(golang:1.24 は 3.21.12-11、Ubuntu 24.04 は 3.21.12-8.2ubuntu0.3)
protoc-gen-go v1.34.2 go install で取得
protoc-gen-go-grpc 1.4.0 go install で取得
google.golang.org/grpc v1.64.0 go get で取得

注意:golang 公式イメージは Debian ベースです

本記事のビルドは golang:1.24 公式イメージ(中身は Debian 13 trixie)で実行しています。実機の Ubuntu 24.04 でも apt install protobuf-compiler で同じ protoc 3.21.12 が入ることは ubuntu:24.04 での apt-cache policy でも確認済みです。ただし Ubuntu の golang-go パッケージは 24.04 でも Go 1.22 止まりなので、最新の Go を使う場合は golang 公式イメージまたは公式バイナリを使ってください。

ツールチェーンのインストール

手順1:golang 公式イメージを起動する(Docker の場合)

ローカル環境を汚さずに試す場合は、Go がすでに入った公式イメージが一番簡単です。




ubuntu@linuxlab: ~
$ docker run -it –rm golang:1.24 bash
root@a1b2c3d4:/go#
$ go version
go version go1.24.13 linux/arm64
Go + protoc + プラグインのバージョン確認(実測)
Go + protoc + プラグインのバージョン確認(実測)

上の実測結果の通り、golang:1.24 イメージには Go 1.24.13 が含まれています(出力の arm64 は Apple Silicon 上で実行したためで、x86_64 環境なら amd64 と表示されます)。

手順2:protobuf-compiler(protoc)をインストールする




ubuntu@linuxlab: ~ (golang:1.24)
$ apt-get update
Reading package lists… Done
$ apt-get install -y protobuf-compiler
0 upgraded, 6 newly installed, 0 to remove and 40 not upgraded.
Unpacking libprotobuf32t64:arm64 (3.21.12-11) …
Setting up protobuf-compiler (3.21.12-11) …
$ protoc –version
libprotoc 3.21.12
protobuf-compiler の apt install 実ログ(実測)
protobuf-compiler の apt install 実ログ(実測)

protoc --versionlibprotoc 3.21.12 と表示されれば成功です。golang:1.24 では protobuf-compiler 本体に加えて libprotobuf32t64 など合わせて6パッケージが入ります(実測)。実機の Ubuntu 24.04 でも同じ 3.21.12 系(3.21.12-8.2ubuntu0.3)が提供されています。

手順3:Go 向けプラグインをインストールする

protoc 単体ではGoコードを生成できません。protoc-gen-go(メッセージ用)と protoc-gen-go-grpc(サービス用)の2つのプラグインが必要です。




ubuntu@linuxlab: ~ (golang:1.24)
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2
go: downloading google.golang.org/protobuf v1.34.2
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4.0
go: downloading google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0
$ $(go env GOPATH)/bin/protoc-gen-go –version
protoc-gen-go v1.34.2
$ $(go env GOPATH)/bin/protoc-gen-go-grpc –version
protoc-gen-go-grpc 1.4.0

インストール後、$GOPATH/bin(golang:1.24 では /go/bin)に protoc-gen-goprotoc-gen-go-grpc が生成されます。protoc はこれらを PATH から探すので、$GOPATH/binPATH に追加しておきましょう。




ubuntu@linuxlab: ~
$ export PATH=$PATH:$(go env GOPATH)/bin
# ~/.bashrc に追記して永続化する場合
$ echo ‘export PATH=$PATH:$(go env GOPATH)/bin’ >> ~/.bashrc

proto ファイルを定義する

gRPC の開発は .proto ファイルの定義から始まります。シンプルな「挨拶サービス」を例に説明します。SayHello という1つのRPCを持つだけの最小構成です。




ubuntu@linuxlab: ~/grpctest/proto/greeter.proto
syntax = “proto3”;
option go_package = “example.com/grpctest/gen;gen”;
package greeter;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest { string name = 1; }
message HelloReply { string message = 1; string timestamp = 2; }

go_package の指定が重要

option go_package には必ずドット(.)またはスラッシュ(/)を含むパスを指定してください。"greeter" のような単純な文字列を指定すると protoc-gen-go: invalid Go import path エラーになります。"example.com/grpctest/gen;gen" の形式(インポートパス;パッケージ名)が安全です。ここでは生成先ディレクトリ gen をパッケージ名に合わせています。

protoc でコードを生成する

proto ファイルを定義したら、protoc でGoコードを生成します。--go_out がメッセージ型、--go-grpc_out がサービス(サーバー/クライアント)用です。




ubuntu@linuxlab: ~/grpctest
$ mkdir -p gen
$ protoc \
–go_out=./gen –go_opt=paths=source_relative \
–go-grpc_out=./gen –go-grpc_opt=paths=source_relative \
–proto_path=./proto ./proto/greeter.proto
$ ls -lh gen/
-rw-r–r– 1 root root 6.6K Jun 14 05:59 greeter.pb.go
-rw-r–r– 1 root root 3.6K Jun 14 05:59 greeter_grpc.pb.go
$ wc -l gen/*.go
221 gen/greeter.pb.go
110 gen/greeter_grpc.pb.go
331 total
protoc コンパイルで Go コード生成(実測)
protoc コンパイルで Go コード生成(実測)

実測では greeter.pb.go(221行・6.6KB)と greeter_grpc.pb.go(110行・3.6KB)の合計331行が生成されました(2026-06-14 実測)。greeter.pb.go はメッセージ型(HelloRequest/HelloReply)、greeter_grpc.pb.go はサービスのサーバー/クライアントインターフェースが含まれています。RPCを増やしたりストリーミングを足すと、この行数はさらに増えていきます。

gRPC サーバーを実装する

まず Go モジュールを初期化して依存パッケージを追加します。




ubuntu@linuxlab: ~/grpctest
$ go mod init example.com/grpctest
go: creating new go.mod: module example.com/grpctest
$ go get google.golang.org/grpc@v1.64.0
go: downloading google.golang.org/grpc v1.64.0
$ go get google.golang.org/protobuf@v1.34.2

次にサーバーを実装します。server/main.go を作成してください。生成された UnimplementedGreeterServer を埋め込み、SayHello を実装するだけです。




ubuntu@linuxlab: ~/grpctest/server/main.go
package main

import (
“context”
“fmt”
“log”
“net”
“time”

“google.golang.org/grpc”
pb “example.com/grpctest/gen”
)

type server struct{ pb.UnimplementedGreeterServer }

func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
msg := “Hello, ” + req.GetName() + “! (gRPC on Ubuntu 24.04)”
return &pb.HelloReply{Message: msg, Timestamp: time.Now().UTC().Format(time.RFC3339)}, nil
}

func main() {
lis, err := net.Listen(“tcp”, “:50051”)
if err != nil { log.Fatalf(“listen error: %v”, err) }
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
fmt.Println(“gRPC server listening on :50051”)
if err := s.Serve(lis); err != nil { log.Fatalf(“serve error: %v”, err) }
}

gRPC クライアントを実装する

client/main.go を作成します。サーバーに接続して SayHello を呼び出す最小実装です。

grpc.Dial は非推奨。grpc.NewClient を使う

古い記事では grpc.Dial(...) をよく見かけますが、grpc v1.64 では grpc.Dial は非推奨(deprecated)です。今回は実測でも問題なく動いた現行の grpc.NewClient(...) を使います。NewClient は接続先を指定するだけで、実際の接続は最初のRPC呼び出し時に確立されます。




ubuntu@linuxlab: ~/grpctest/client/main.go
package main

import (
“context”
“fmt”
“log”
“time”

“google.golang.org/grpc”
“google.golang.org/grpc/credentials/insecure”
pb “example.com/grpctest/gen”
)

func main() {
conn, err := grpc.NewClient(“localhost:50051”,
grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil { log.Fatalf(“dial error: %v”, err) }
defer conn.Close()

c := pb.NewGreeterClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

r, err := c.SayHello(ctx, &pb.HelloRequest{Name: “LinuxLab”})
if err != nil { log.Fatalf(“SayHello error: %v”, err) }
fmt.Printf(“Response: %s (at %s)\n”, r.GetMessage(), r.GetTimestamp())
}

サーバーとクライアントを動かす

依存を整理してビルドし、サーバーをバックグラウンドで起動してからクライアントを実行します。




ubuntu@linuxlab: ~/grpctest
$ go mod tidy
$ go build -o grpc-server ./server/ && go build -o grpc-client ./client/
built grpc-server
built grpc-client
$ ./grpc-server &
gRPC server listening on :50051
$ ss -tlnp | grep 50051
LISTEN 0 4096 *:50051 *:* users:((“grpc-server”,pid=3177,fd=3))
$ ./grpc-client
Response: Hello, LinuxLab! (gRPC on Ubuntu 24.04) (at 2026-06-14T06:00:45Z)
gRPCサーバー起動とクライアント通信の実測スクリーンショット
gRPCサーバー起動とクライアント通信の実測スクリーンショット

クライアントから SayHello が呼び出され、サーバーが返した文字列とタイムスタンプ(2026-06-14T06:00:45Z)が表示されました。ss -tlnp でも grpc-server プロセスが 50051 番ポートをリッスンしていることが確認できます。Protocol Buffers によるシリアライズ/デシリアライズはすべて自動です。

著者アイコン
著者アイコン

正直、最初に詰まったのは go_package の書き方でした。"greeter" だけ書くとエラーになります。"example.com/grpctest/gen;gen" のようにモジュールパスの形式で書くと通ります。あと、古い記事のまま grpc.Dial で書くと非推奨の警告が出るので、新しく書くなら grpc.NewClient がおすすめです。ここさえ押さえれば、あとは手順通りで動きます。

Ubuntu 22.04 vs 24.04 パッケージ比較

Ubuntu 22.04・24.04・golang:1.24 イメージの3環境で apt-cache policy を実際に実行し、gRPC関連パッケージのバージョンを比較しました(2026-06-14 実測)。

Ubuntu 22.04 / 24.04 / golang:1.24 gRPC関連パッケージ比較(実測)
Ubuntu 22.04 / 24.04 / golang:1.24 gRPC関連パッケージ比較(実測)

Ubuntu 22.04 の protobuf-compiler3.12.4-1ubuntu7.22.04.6 と古く、golang-go も Go 1.18 止まりです。一方 Ubuntu 24.04 では protoc が 3.21.12-8.2ubuntu0.3 まで上がりますが、golang-go24.04 でも Go 1.22 止まりでした。ジェネリクスや slices/maps パッケージ、新しいツールチェーンを使いたい場合は、apt の Go に頼らず golang:1.24 公式イメージ(Go 1.24.13 同梱)か公式バイナリを使うのが確実です。

よくあるエラーと解決策

①protoc-gen-go: program not found or is not executable

protoc-gen-go が PATH に入っていないときに出るエラーです。go install でプラグインは入れたのに、$GOPATH/bin を PATH に追加していないと発生します。




ubuntu@linuxlab: ~
protoc-gen-go: program not found or is not executable
–go_out: protoc-gen-go: Plugin failed with status code 1.

# 解決策: $GOPATH/bin を PATH に追加する
$ export PATH=$PATH:$(go env GOPATH)/bin
$ protoc –go_out=… # 再実行

②invalid Go import path エラー

go_package にドットもスラッシュも含まない名前を書いたときに出ます。




ubuntu@linuxlab: ~
protoc-gen-go: invalid Go import path “greeter” for “greeter.proto”
The import path must contain at least one period (‘.’) or forward slash (‘/’) character.

# .proto ファイルの go_package を修正する
# NG: option go_package = “greeter”;
# OK: option go_package = “example.com/grpctest/gen;gen”;

③context deadline exceeded(クライアント接続失敗)

サーバーが起動していない、またはポートが違うときに発生します。サーバーが :50051 でリッスンしているか ss で確認してください。




ubuntu@linuxlab: ~
$ ss -tlnp | grep 50051
LISTEN 0 4096 *:50051 *:* users:((“grpc-server”,pid=3177,fd=3))
# ↑ このように表示されればサーバーは起動している

まとめ

golang:1.24 公式イメージ(Go 1.24.13)で gRPC + Protocol Buffers を動かす手順を、実際にビルド・通信させて確認しました。

  • apt install protobuf-compiler → protoc 3.21.12 が入る(golang:1.24・Ubuntu 24.04 とも 3.21.12 系、2026-06-14 実測)
  • go installprotoc-gen-go v1.34.2protoc-gen-go-grpc 1.4.0 を追加する
  • .protogo_package はドットかスラッシュを含む形式で書く
  • protoc 1コマンドで *.pb.go*_grpc.pb.go が自動生成される(実測で 221行+110行=331行)
  • クライアントは grpc.Dial(非推奨)ではなく grpc.NewClient を使う
  • Ubuntu 22.04 は protoc 3.12.4・Go 1.18 と古い。新しい環境で組むなら 24.04 系を推奨

マイクロサービス間の通信に gRPC を導入すると、型安全さと高速なバイナリ通信の両方が得られます。VPS でサービスを本番運用する際は、ファイアウォール(UFW)で gRPC のポート(デフォルト 50051)を必要な相手だけに開けるなど、アクセス制御も忘れずに行いましょう。

gRPC サーバーを VPS に乗せて本番運用する際の選び方は VPS比較の記事 でも紹介しています。学習用なら東京リージョンのある安価なプランから始めるのがおすすめです。

コメント

タイトルとURLをコピーしました