构建一个包含多个Proto文件的Docker – 找不到Proto文件

huangapple go评论91阅读模式
英文:

Building a Docker with Multiple Proto - Proto File not found

问题

我遇到了一个问题,无法构建包含多个proto文件(服务器和文本)的Dockerfile。服务器proto文件位于Dockerfile目录中,但文本proto文件位于Dockerfile的父目录中。因此,我在父目录中构建Dockerfile以将文本proto文件复制到Docker构建中。

尽管我将proto/text.proto复制到与server/proto/server.proto相同的位置,但Docker构建仍然报错proto/text.proto: File not found.

以下是我所有的文件:

DockerFile

FROM --platform=linux/x86_64 golang:1.19.3-bullseye

# Install grpc
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 && \
    go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28

WORKDIR /app
COPY server/. /app
COPY proto/text.proto /app/proto/text.proto

# Install protoc and zip system library
RUN apt-get update && apt-get install -y zip && \
    mkdir /opt/protoc && cd /opt/protoc && wget https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protoc-3.7.0-linux-x86_64.zip && \
    unzip protoc-3.7.0-linux-x86_64.zip

# Copy the grpc proto file and generate the go module
RUN /opt/protoc/bin/protoc --go_out=/app/proto --proto_path=/app/proto --go_opt=paths=source_relative --go-grpc_out=/app/proto --go-grpc_opt=paths=source_relative /app/proto/text.proto /app/proto/server.proto

EXPOSE 5051
RUN go build -o /server
ENTRYPOINT ["/server"]

目录树

1.text
    ├── admin
    │    ├── Dockerfile
    │    ├── app.js
    │    ├── package.json
    │    └── web
    │        ├── html
    │        │    └── index.html
    │        └── resources
    ├── compose.yaml
    ├── db
    │    ├── Dockerfile
    │    ├── main.go
    │    ├── proto
    │    │    ├── db.pb.go
    │    │    ├── db.proto
    │    │    └── db_grpc.pb.go
    │    └── text.db
    ├── go.mod
    ├── go.sum
    ├── proto
    │    ├── text.pb.go
    │    └── text.proto
    └── server
        ├── Dockerfile
        ├── main.go
        ├── proto
        │    ├── server.pb.go
        │    ├── server.proto
        │    └── server_grpc.pb.go
        └── text
            ├── text.go
            └── text_test.go

我能够在根目录的text目录中运行以下protoc命令:

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/text.proto db/proto/db.proto server/proto/server.proto

并在本地运行服务器,但无法构建我的Docker镜像:

CMD

docker build -f server/Dockerfile -t server .

错误

=> ERROR [7/8] RUN /opt/protoc/bin/protoc --go_out=/app/proto --proto_path=/app/proto --go_opt=paths=source_relative --go-grpc_out=/app/proto --go-grpc_opt=paths=source_relative   0.4s
------
 > [7/8] RUN /opt/protoc/bin/protoc --go_out=/app/proto --proto_path=/app/proto --go_opt=paths=source_relative --go-grpc_out=/app/proto --go-grpc_opt=paths=source_relative /app/proto/text.proto /app/proto/server.proto:
#11 0.427 proto/text.proto: File not found.
#11 0.429 server.proto: Import "proto/text.proto" was not found or had errors.
#11 0.431 server.proto:25:5: "text.Status" seems to be defined in "text.proto", which is not imported by "server.proto".  To use it here, please add the necessary import.
------
executor failed running [/bin/sh -c /opt/protoc/bin/protoc --go_out=/app/pro
text/server/proto
syntax="proto3";
package server;

import "proto/text.proto";
option go_package = "github.com/amb1s1/text/server/proto/server";

message SendMessageRequest {
    string token = 1;
    string phone = 2;
    string message = 3;
    bool dry_run = 4;
};

message SendMessageResponse {
    text.Status status = 1;
};

service Text {
    // SendMessage sents SMS message.
    rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) {}
}

text/proto/

syntax="proto3";

package text;

option go_package = "github.com/amb1s1/text/proto";

enum Status {
    UNKNOW = 0;
    OK = 1;
    TOKENS_EXISTS = 2;
    TOKEN_NOT_FOUND = 3;
    FAILED_NOT_SENT= 4;
    DRY_RUN_OK = 5;
    ZERO_BALANCE = 6;
    WRONG_TOKEN = 7;
}
英文:

I'm running with an issue where I can't build Dockerfile that includes multiple proto files(server and text). The server proto is within the Dockerfile dir, but the text proto is within the Dockerfile parent. So I'm building the Dockerfile in the parent dir to COPY the text proto to the Docker build.

The Docker build complaining about proto/text.proto: File not found. even though I COPY the proto/text.proto to the exact location as server/proto/server.proto.

Here are all my files:

DockerFile

FROM --platform=linux/x86_64 golang:1.19.3-bullseye

# Install grpc
RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 && \
    go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28

WORKDIR /app
COPY server/. /app
COPY proto/text.proto /app/proto/text.proto

# Install protoc and zip system library
RUN apt-get update && apt-get install -y zip && \
    mkdir /opt/protoc && cd /opt/protoc && wget https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protoc-3.7.0-linux-x86_64.zip && \
    unzip protoc-3.7.0-linux-x86_64.zip

# Copy the grpc proto file and generate the go module
RUN /opt/protoc/bin/protoc --go_out=/app/proto --proto_path=/app/proto --go_opt=paths=source_relative --go-grpc_out=/app/proto --go-grpc_opt=paths=source_relative /app/proto/text.proto /app/proto/server.proto

EXPOSE 5051
RUN go build -o /server
ENTRYPOINT ["/server"]

Dir Tree

1.text
    ├── admin
    │   ├── Dockerfile
    │   ├── app.js
    │   ├── package.json
    │   └── web
    │       ├── html
    │       │   └── index.html
    │       └── resources
    ├── compose.yaml
    ├── db
    │   ├── Dockerfile
    │   ├── main.go
    │   ├── proto
    │   │   ├── db.pb.go
    │   │   ├── db.proto
    │   │   └── db_grpc.pb.go
    │   └── text.db
    ├── go.mod
    ├── go.sum
    ├── proto
    │   ├── text.pb.go
    │   └── text.proto
    └── server
        ├── Dockerfile
        ├── main.go
        ├── proto
        │   ├── server.pb.go
        │   ├── server.proto
        │   └── server_grpc.pb.go
        └── text
            ├── text.go
            └── text_test.go

I'm able to run the following protoc in the root text dir:

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/text.proto db/proto/db.proto server/proto/server.proto

And run the server locally, but I'm not able to build my Docker:

CMD

docker build -f server/Dockerfile -t server .

Error

=> ERROR [7/8] RUN /opt/protoc/bin/protoc --go_out=/app/proto --proto_path=/app/proto --go_opt=paths=source_relative --go-grpc_out=/app/proto --go-grpc_opt=paths=source_relative   0.4s
------
 > [7/8] RUN /opt/protoc/bin/protoc --go_out=/app/proto --proto_path=/app/proto --go_opt=paths=source_relative --go-grpc_out=/app/proto --go-grpc_opt=paths=source_relative /app/proto/text.proto /app/proto/server.proto:
#11 0.427 proto/text.proto: File not found.
#11 0.429 server.proto: Import "proto/text.proto" was not found or had errors.
#11 0.431 server.proto:25:5: "text.Status" seems to be defined in "text.proto", which is not imported by "server.proto".  To use it here, please add the necessary import.
------
executor failed running [/bin/sh -c /opt/protoc/bin/protoc --go_out=/app/pro
text/server/proto
syntax="proto3";
package server;

import "proto/text.proto";
option go_package = "github.com/amb1s1/text/server/proto/server";

message SendMessageRequest {
    string token = 1;
    string phone = 2;
    string message = 3;
    bool dry_run = 4;
};

message SendMessageResponse {
    text.Status status = 1;
};

service Text {
    // SendMessage sents SMS message.
    rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) {}
}

text/proto/

syntax="proto3";

package text;

option go_package = "github.com/amb1s1/text/proto";

enum Status {
    UNKNOW = 0;
    OK = 1;
    TOKENS_EXISTS = 2;
    TOKEN_NOT_FOUND = 3;
    FAILED_NOT_SENT= 4;
    DRY_RUN_OK = 5;
    ZERO_BALANCE = 6;
    WRONG_TOKEN = 7;
}

答案1

得分: 3

根据评论,您的Docker镜像中有以下目录结构:

/app/proto/server.proto 
/app/proto/text.proto

server.proto 使用 import "proto/text.proto" 导入了 text.proto

这意味着 protoc 将在导入路径中查找名为 proto/text.proto 的文件。您在 protoc 的参数中指定了 --proto_path=/app/proto,这意味着 protoc 将检查 /app/proto/proto/text.proto,但该文件不存在(因此出现了问题)。要解决此问题,请删除 --proto_path=/app/proto(这样 protoc 将使用工作文件夹)或指定 --proto_path=/app

英文:

As per the comments; within your docker image you have the directory structure:

/app/proto/server.proto 
/app/proto/text.proto

server.proto imports text.proto with import "proto/text.proto".

This means that protoc will be looking for a file called proto/text.proto within the import path. You specified --proto_path=/app/proto as an argument to protoc meaning that protoc will check for /app/proto/proto/text.proto which does not exist (hence the issue). To fix this remove the --proto_path=/app/proto (so protoc uses the working folder) or specify --proto_path=/app.

huangapple
  • 本文由 发表于 2022年11月13日 00:29:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/74414655.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定