【问题标题】:go build fails to find local dependencies on dockergo build 找不到 docker 上的本地依赖
【发布时间】:2021-12-03 06:41:10
【问题描述】:

我正在尝试为我的 go 服务器创建一个 dockerfile,但它一直失败,因为它无法识别一些本地依赖项(它们是代码本身的模块,而不是外部依赖项)。

示例:

import (
    "<private-repo-url>/src/cmd/http-api/bootstrap" // this a local module that's part of the server
    "go.uber.org/fx"
)

func main() {
    fx.New(bootstrap.Module).Run()
}

这是错误:

 => ERROR [7/7] RUN go build -a -o ./server                                                                                                                                                                        0.3s
------
 > [7/7] RUN go build -a -o ./server:
#10 0.295 server.go:4:2: no required module provides package <private-repo-url>/src/cmd/http-api/bootstrap; to add it:
#10 0.295       go get <private-repo-url>/src/cmd/http-api/bootstrap
------
executor failed running [/bin/sh -c go build -a -o ./server]: exit code: 1

请注意,这个 private-repo-url 对应于该应用程序的存储库(它不是外部依赖项)。

这是 Dockerfile

FROM golang:1.17

WORKDIR /balrog

# Copy dependency definitions and download them
ADD go.mod .
ADD go.sum .
RUN go mod download

# Build the binary
ADD ./src .
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
RUN go build -a -o ./server

#Run the server
CMD ["/server"]

还有 mod.go 文件:

module <private-repo-url>

go 1.16

require (
    github.com/gin-gonic/gin v1.7.7
    github.com/google/uuid v1.3.0
    github.com/kelseyhightower/envconfig v1.4.0
    github.com/sirupsen/logrus v1.8.1
    go.uber.org/fx v1.15.0
)

我读过 GO111MODULE 说它应该是on,我还读到它从 1.17 (here) 开始默认启用。

根据官方 docker 镜像(dockerhub),正确的方法是在复制所有文件后使用 go getgo install。这种方法使我遇到了一个稍微不同的问题,即 docker 无法访问存储库(因为它是私有的)并且我想避免向 docker 添加凭据。

我尝试使用环境变量 GOVCS 设置它的值,例如:

ENV GOVCS=github.com:git,gitlab.com:off

但它仍然失败并出现同样的错误。

最后我尝试了替换,我认为如果我从本地依赖项中删除它会起作用,所以我执行(在 Dockerfile 中)这个:

RUN go mod edit -replace &lt;private-repo-url&gt;=./

再次失败:

 => ERROR [builder 10/10] RUN go build -a -o ./server                                                                                                                                                              0.3s
------                                                                                                                                                                                                                  
 > [builder 10/10] RUN go build -a -o ./server:                                                                                                                                                                         
#17 0.299 server.go:4:2: module <private-repo-url>/src provides package <private-repo-url>/src/cmd/http-api/bootstrap and is replaced but not required; to add it:
#17 0.299       go get <private-repo-url>/src
#17 0.299 server.go:5:2: no required module provides package go.uber.org/fx; to add it:
#17 0.299       go get go.uber.org/fx

有什么方法可以阻止 go builder/package installer 从外部寻找这些文件? go modgo get + go install 都尝试访问此私有存储库,但由于他们无权访问而失败。但他们不应该首先尝试访问它,因为它是应用程序的存储库......或者是我做错了什么(显然或者我不会在这里),遗漏了什么?

【问题讨论】:

  • 包裹&lt;private-repo-url&gt;/src/cmd/http-api/bootstrap在哪里?如果它不在同一个存储库中,那么go build 必须尝试获取它。还可以尝试将您正在构建的包完全限定为go build 的最后一个参数;我不知道您的主包相对于您的go.mod 位于何处。
  • go.dev/doc/tutorial谈如何在这种情况下成功使用replace
  • 问题正如另一条评论中指出的那样,ADD ./src . 没有维护依赖项导入中引用的 src 文件夹,这就是在本地找不到这些依赖项和构建的原因进程确实尝试从存储库中获取它们。

标签: go dockerfile go-modules go-get


【解决方案1】:

ADD ./src . - 将src 的内容复制到当前文件夹,剥离src 部分。

应该只是COPY . ./

另请注意,不建议在源代码树中包含 src 子文件夹 - 包含 go.mod 的文件夹已经是源代码树。

【讨论】:

  • 它确实有效!我花了几个小时在这上面,就这么简单。非常感谢!关于没有 src 文件夹,我们计划使用它来将源与存储库中包含的其他文件(如 CI 配置、k8s 等)分开。有没有更好的方法来解决这个问题?
  • Go 将配置文件与 Go 源一起存储不是问题。出于这个原因,人们通常只是不将它们分开。不过有用的是进行多阶段构建,以便从最终图像中排除 Go SDK 和项目源。有关详细信息,请参阅this answer
猜你喜欢
  • 2021-10-08
  • 1970-01-01
  • 2021-02-02
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多