【问题标题】:Unable to Successfully Build Go-Based Docker Image无法成功构建基于 Go 的 Docker 映像
【发布时间】:2021-06-30 18:15:42
【问题描述】:

在尝试构建基于 GoLang 的 Docker 映像时,Docker 执行器遇到以下错误:

。 . .go: $GIT_REPO@v1.9.11: 在版本 v0.0.07 读取 $GIT_REPO/go.mod: 未知版本 v0.0.07

在使用Dockerfile 的以下RUN 指令处:

RUN go build . . .

GIT_REPO 代表私有仓库。完整路径,包括所有者和名称。

Docker 执行器在go1.13.x 及更高版本中遇到此错误; Docker 执行程序确实不会遇到go1.12.x 的此错误。

供应商目录。包含所有个必需的包。标签已确认存在。

甚至将正确的 SSH 密钥添加到私有 Go 通用存储库中。成功了

git clone . . .

building Docker 镜像之外的命令,但仍然遇到上述相同的错误。

【问题讨论】:

  • 你能粘贴go env的结果吗?你使用 go 模块吗?项目是否在 GOPATH 内?
  • 永远不要将密钥/秘密签入 git repo - 即使它是私人 repo。这样做不会修复您的 Docker 构建失败(repo 是私有的,因此 docker 构建无论如何都无法获取密钥)。请参阅下面有关如何从私有仓库构建 Docker 的答案。
  • 我在本地 bitbucket 和 Go 1.15.3 上也遇到了同样的问题。我无法弄清楚构建容器缺少什么。否则发现修订版很好,只会在构建容器内失败。有人找到解决方案了吗?

标签: docker go


【解决方案1】:

编辑:

验证您在bitbucket.org 中的远程存储库实际上具有您尝试构建的v0.0.7 标记。

如果 git 标签在本地存在,则本地构建可能会工作 - 如果标签不存在 远程,docker 构建将从远程源中提取并失败并出现 go.mod at revision v0.0.7: unknown revision v0.0.7 之类的错误。

将本地标签推送到远程仓库:

git push --tags

更精细的标签操作see


Docker 构建默认只能访问公共仓库。由于您需要访问私有仓库,因此您需要在 Docker 构建过程中包含一个 read-ssh 密钥(永远不要将密钥签入仓库!)。

非常重要,但是,您在 multi-stage build 中执行此操作,因此您不会在最终映像中包含您的 SSH 密钥。

这个blog post 完成了所有步骤。但要包括一个工作示例:

构建 docker 镜像:

SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)" \
    docker build -t "myapp:v0.0.1" --build-arg SSH_PRIVATE_KEY .

Dockerfile 使用bitbucket.org 私人回购网站:

FROM golang:1.14.6 AS build
  
WORKDIR /bld
COPY *.go go.mod go.sum ./

ARG SSH_PRIVATE_KEY
# ***NEVER*** DO THIS IN A SINGLE-STAGE DOCKER BUILD (see below)
RUN \
        mkdir -p ~/.ssh && \
        umask 0077 && \
        echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa && \
        git config --global url."git@bitbucket.org:".insteadOf https://bitbucket.org/ && \
        ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts

RUN \
        go get && \
        CGO_ENABLED=0 go build -o app

# final stage of multi-stage: will appropriately *NOT* include SSH keys
FROM scratch

COPY --from=build \
        /etc/ssl /etc/ssl

COPY --from=build \
    /bld/app /app/myapp

CMD ["/app/myapp"]

【讨论】:

  • 谢谢,我已经试过了,但没有帮助。 git clone 可以完成这项工作,但 go get 会为所有私人仓库抛出未知修订版 谢谢
  • 我们正在使用 bitbucket
  • @kotyara85 你确定你已经将v0.0.7 标签推送到你的远程私人仓库了吗?如果标签是 local,您可能能够在本地构建 - 但由于 Go 模块构建将从 remote URL 提取代码,因此它可能会丢失。在 bitbucket.org 网站上验证您的标签,如果丢失 - git push --tags
  • 是的,我确实推送了所有标签。即使我删除所有包,本地构建也能正常工作
  • 我在bitbucket.og 中创建了一个私有仓库 - 并使用了上述设置 - 并且能够通过 docker 构建私有仓库。您必须缺少一些微妙的步骤。你的主要 repo 的 go.mod 文件是什么样的?我希望没有replace 指令?
【解决方案2】:

这里有两个问题需要解决:

1.如何让 Docker 安全地访问本地 SSH 密钥?

2.如何告诉 Go 不要使用公共注册表来获取私有包?


简答

  1. Docker v18.09 开始,有一个内置的解决方案可以在构建阶段处理 SSH 身份验证 (more)。与传递构建参数相比,它也更容易、更安全,并且无需多阶段 Docker 构建。

  2. Go 有一个 GOPRIVATE 环境变量来识别私有包。 (more)


长答案

一步一步:

1.确保 ssh-agent 已设置并且知道 SSH 密钥

Github 有一个关于这个主题的快速指南,解释了不同操作系统的过程。见Generating a new SSH key and adding it to SSH agent

2。为 Docker 启用 BuildKit

如果没有 BuildKitdocker build 将无法识别 --ssh 选项。

来自Docker reference

全新安装 docker 最简单的方法是设置 DOCKER_BUILDKIT=1 调用 docker build 时的环境变量 命令,如:

$ DOCKER_BUILDKIT=1 docker build .

通过以下方式启用 docker BuildKit 默认,在/etc/docker/daemon.json 功能中设置守护进程配置 为 true 并重新启动守护进程:

{ "features": { "buildkit": true } }

Docker Desktop 用户可以通过Preferences > Docker Engine管理守护进程配置。

4.更新 Dockerfile

4.1.确保 Git 使用 SSH 而不是 HTTPs

Go 倾向于通过HTTPs 获取公共包。您可以通过更新git 配置来调整此行为:

RUN git config --global url.git@github.com:.insteadOf https://github.com/

您可能也应该在本地计算机上执行此操作。

4.2.在需要的地方请求 SSH 访问

每个需要 SSH 访问的RUN 命令都应该使用type=ssh 挂载。对于

例子:

RUN --mount=type=ssh git clone ...

4.3.确保 Go 知道你的私有包

更新GOPRIVATE变量:

RUN go env -w GOPRIVATE="github.com/your-org/private-repo"

将所有这些放在一起,在以下 Dockerfile 示例中:

FROM golang:1.16.3-alpine3.13
RUN apk update
RUN apk add git openssh
RUN mkdir /app
ADD . /app
WORKDIR /app

# You can replace github.com with any other Git host
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts

# Make sure git uses SSH to fetch packages, not HTTPs
RUN git config --global url.git@github.com:.insteadOf https://github.com/

# Make Go knows which packages are private.
RUN go env -w GOPRIVATE="github.com/your-org/private-repo"
# GOPRIVATE is a comma separated list glob-patterns.
# You can use a wildcard to match every repo in an organization:
#   e.g.: GOPRIVATE="github.com/your-org/*"

# Mount the build command with type `ssh`.
RUN --mount=type=ssh go get && go build -o main .

CMD ["/app/main"]

6.使用--ssh 选项构建镜像:

默认启用 BuildKit:

$ docker build --ssh default -t my-app:latest .

【讨论】:

  • 虽然这是实现这一目标的最准确方法,但现在最好提一下docker-compose build does not support --ssh ;-(,因此您需要使用@987654347 构建图像@在使用docker-compose之前。
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多