Building a Docker with Multiple Proto – Proto File not found

Issue

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;
}

Solution

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.

Answered By – Brits

Answer Checked By – Robin (GoLangFix Admin)

Leave a Reply

Your email address will not be published.