Go build binary failed - pull from private failed



在 go 專案下要 build bin 檔的時候出現 error :

34.21 go: xxxx.com/qson/libraries/qlib@v0.2.73: unrecognized import path "xxxx.com/yy/libraries/qlib": https fetch: Get "https://xxxx.com/yy/libraries/lib?go-get=1": dial tcp 122.17.60.101:443: connect: no route to host
------
Dockerfile:34
--------------------
  33 |     COPY go.* .
  34 | >>> RUN --mount=type=secret,id=netrc,dst=/root/.netrc \
  35 | >>>     --mount=type=cache,target=/go/pkg/mod \
  36 | >>>     --mount=type=cache,target=/root/.cache/go-build \
  37 | >>>     go install github.com/swaggo/swag/cmd/swag@latest && \
  38 | >>>     go install github.com/t-yuki/gocover-cobertura@latest && \
  39 | >>>     go install gotest.tools/gotestsum@latest && \
  40 | >>>     go install google.golang.org/protobuf/cmd/protoc-gen-go@latest && \
  41 | >>>     go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest && \
  42 | >>>     go mod download
  43 |     
--------------------
ERROR: failed to solve: process "/bin/sh -c go install github.com/swaggo/swag/cmd/swag@latest &&     go install github.com/t-yuki/gocover-cobertura@latest &&     go install gotest.tools/gotestsum@latest &&     go install google.golang.org/protobuf/cmd/protoc-gen-go@latest &&     go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest &&     go mod download" did not complete successfully: exit code: 1

這是由於 go.mod 中有一個私有模組,但 Docker 容器在 go mod download 的時候連不到內部伺服器,所以整個步驟失敗。

Solution

  1. 在可以連到內部伺服器的主機上先: go mod vendor,然後 Dockerfile 改成:
     COPY go.* .
     COPY vendor/ vendor/
     RUN go mod vendor && \
         go install ...
    

    這樣 build 時不需要再上網抓私有套件。

  2. 把 go mod download 刪掉

什麼是 go mod vendor

  • 平常 Go build 會去網路下載依賴(go mod download),這時如果有私有模組、外網斷線,就會失敗。用 go mod vendor 把依賴先放進 vendor/ 後,Go build 可以直接從 vendor/ 讀取,不必再連網抓套件,適合離線建置或有內部私有依賴的情況。
  • Go 1.14+ 開始,go build、go install 會自動偵測 vendor/ 並使用它(除非用 -mod=readonly 或 -mod=mod 強制不用)。
  • 缺點:vendor 資料夾可能很大、若有新版本需要重新 go mod vendor