Google Cloud Container Builder - 使用 vendored 依赖项从 Go 源构建 Docker 容器

Google Cloud Container Builder - Build Docker container from Go source with vendored dependencies

背景

相关问题:

我正在尝试使用 Google Cloud Container Builder 来使用构建触发器自动构建我的 Docker 容器。

我的代码在 Go 中,我的项目根目录中有一个 vendor 文件夹(已签入 Git),其中包含我所有的 Go 依赖项。

我的项目有四个二进制文件需要Docker化,结构如下:

vendor/
   ...
program1/
    program1.go
    main/
        main.go
        Dockerfile
program2/
    program2.go
    main/
        main.go
        Dockerfile
...

每个程序的Docker文件很简单:

FROM alpine
ADD main main
ENTRYPOINT ["/main"]

我设置了构建触发器来跟踪我的 master 分支。触发器运行以下构建请求 (cloudbuild.yaml),它使用开源 Docker 构建步骤:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/program1:0.1.15-$SHORT_SHA', '.']
  dir: 'program1/main'

  ... (repeated for each program)
  (images, tags omitted)

总结一下,我目前的构建过程如下:

  1. 编辑代码。
  2. 使用 go build 构建每个 Go 可执行文件。可执行文件名为 main,并与 main.go.
  3. 一起保存在 programX/main/ 目录中
  4. 提交并推送代码(因为 main 可执行文件被 Git 跟踪)到我的主分支。
  5. 构建触发器使用步骤 1 中构建的 main 文件制作四张 Docker 图像。

目标

我想从我的构建过程中删除第 1 步,这样我就不再需要在本地编译我的可执行文件,也不需要在 Git 中跟踪我的 main 个可执行文件。

总而言之,这是我理想的过程:

  1. 编辑代码,提交,推送到远程。
  2. Build Trigger 编译所有四个程序,构建所有四个映像。
  3. 放松 :)

尝试的解决方案

我用的是开源的Go build step,如下:

cloudbuild.yaml:(更新)

steps:
- id: 'build-program1'
  name: 'gcr.io/cloud-builders/go'
  args: ['build', '-a', '-installsuffix', 'cgo', '-ldflags', '''-w''', '-o', 'main', './main.go']
  env: ['PROJECT_ROOT=/workspace', 'CGO_ENABLED=0', 'GOOS=linux']
  dir: 'program1/main'
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/program1:0.1.15-$SHORT_SHA', '.']
  dir: 'program1/main'
  waitFor: ['build-program1']

  ... (repeated for each program)
  (images, tags omitted)

build-programXenv 字段中尝试设置 PROJECT_ROOT 和 GOPATH 的各种组合后,我的项目中使用的每个包(文件路径不同):

cannot find package "github.com/acoshift/go-firebase-admin" in any of
Step #0 - "build-program1": /usr/local/go/src/github.com/acoshift/go-firebase-admin (from $GOROOT) 
Step #0 - "build-program1": /workspace/auth/main/gopath/src/github.com/acoshift/go-firebase-admin (from $GOPATH)

它甚至没有在寻找供应商目录?

下一步是什么?

我的猜测是以下其中一项为真:

  1. 我没有在构建请求文件中正确指定 GOPATH/PROJECT_ROOT。但如果是这样,正确的设置是什么?
  2. 我的项目结构不正确。
  3. 我想做的事是不可能的:(*
  4. 我需要以某种方式进行自定义构建步骤。
  5. 使用的 Go 版本旧 - 但我该如何检查?

我无法在网上找到我想要实现的目标的示例,而且我发现 GCP 关于此主题的文档非常缺乏。

如有任何帮助,我们将不胜感激!

问题与 #1 有关:PROJECT_ROOT 指的是您的二进制文件所需的导入路径。例如,如果在 program1/main/main.go 中导入 "github.com/foo/bar/program1" 以获取在 program1/program1.go 中定义的包,则应设置 PROJECT_ROOT=github.com/foo/bar.

修复了问题(但不确定如何...),感谢这些更改:

  1. PROJECT_ROOT 设置为 my_root,以便我要编译的代码位于 my_root/program1/main/main.go(感谢 John Asmuth 的回答:
  2. 删除 Go 构建步骤的 dirs 字段
  3. -o 标志设置为 ./program1/main/main,并将最终构建参数设置为 ./program1/main/main.go

之前我在构建步骤中 cd 进入 program1/main 目录,出于某种原因 go buildmy_root/program1/main 而不是 my_root。奇怪!