假设我们有一个带有gRPC服务定义的services.proto
,例如:
service Foo {
rpc Bar (BarRequest) returns (BarReply) {}
}
message BarRequest {
string test = 1;
}
message BarReply {
string test = 1;
}
我们可以通过运行类似的程序在本地将其编译为Go
$ protoc --go_out=. --go_opt=paths=source_relative
--go-grpc_out=. --go-grpc_opt=paths=source_relative
services.proto
不过,我担心的是,根据安装的protobuf编译器版本和gRPC的Go插件,运行最后一步可能会产生不一致的输出。例如,在同一项目中工作的两个开发人员在本地安装的版本可能略有不同。
对我来说,通过容器化protoc
步骤来解决这个问题似乎是合理的。例如,使用这样的Dockerfile
。。。
FROM golang:1.18
WORKDIR /src
RUN apt-get update && apt-get install -y protobuf-compiler
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
CMD protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative services.proto
我们可以在容器中运行protoc
步骤:
docker run --rm -v $(pwd):/src $(docker build -q .)
在将上一个命令封装在shell脚本中之后,开发人员可以在本地机器上运行它,从而为他们提供确定性的、可复制的输出。它也可以在CI/CD管道中运行。
我的问题是,这是一种合理的方法吗?和/或有没有更容易的方法来实现同样的结果?
注意,我很惊讶地发现,官方的grpc/go图像并没有预装protoc
。我是不是偏离了寻常路?
我的问题是,这是一种合理的方法吗?
这绝对是一个不错的方法。我也这么做。不仅要在整个团队中保持一致,还要确保我们能够在不同的操作系统中产生相同的输出。
不过,有一种更简单的方法可以做到这一点。看看这个回购:https://github.com/jaegertracing/docker-protobuf
图像在Docker hub中,但如果您愿意,可以创建您的图像。
我用这个命令生成Go:
docker run --rm -u $(id -u)
-v${PWD}/protos/:/source
-v${PWD}/v1:/output
-w/source jaegertracing/protobuf:0.3.1
--proto_path=/source
--go_out=paths=source_relative,plugins=grpc:/output
-I/usr/include/google/protobuf
/source/*