2

Background

Related question: Google Container Builder: How to install govendor dependencies during build step?

I am trying to use Google Cloud Container Builder to automate the building of my Docker containers using Build Triggers.

My code is in Go, and I have a vendor folder (checked in to Git) in my project root which contains all of my Go dependencies.

My project has four binaries that need to be Dockerized, structured as follows:

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

Each program's Dockerfile is simple:

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

I have a Build Trigger set up to track my master branch. The trigger runs the following build request (cloudbuild.yaml), which makes use of the open sourced Docker build step:

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)

To summarize, my current build process is as follows:

  1. Edit code.
  2. Build each Go executable using go build. The executable is called main, and is saved in the programX/main/ directory, alongside main.go.
  3. Commit and push code (since the main executables are tracked by Git) to my master branch.
  4. Build Trigger makes four Docker images using the main file built in step 1.

Goal

I would like to eliminate Step 1 from my build process, so that I no longer need to compile my executables locally, and do not need to track my main executables in Git.

In sum, here is my ideal process:

  1. Edit code, commit, push to remote.
  2. Build Trigger compiles all four programs, builds all four images.
  3. Relax :)

Attempted solution

I used the open source Go build step, as follows:

cloudbuild.yaml: (updated)

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)

After trying various combinations of setting PROJECT_ROOT and GOPATH in the env field of the build-programX, I kept getting the same error for every single package used in my project (file path varies):

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)

It's not even looking for a vendor directory?

What next?

My guess is that one of the following is true:

  1. I am not specifying the GOPATH/PROJECT_ROOT correctly in the build request file. But if so, what is the correct setting?
  2. My project is not structured correctly.
  3. What I am trying to do is impossible :(*
  4. I need to make a custom build step, somehow.
  5. The version of Go used is old - but how can I check this?

I can find no examples online of what I am trying to achieve, and I find GCP's documentation on this subject quite lacking.

Any help would be greatly appreciated!

Ismail Khan
  • 842
  • 2
  • 8
  • 20

2 Answers2

3

The issue is with #1: PROJECT_ROOT refers to the desired import path of your binaries. For example, if in program1/main/main.go you import "github.com/foo/bar/program1" to get the package defined in program1/program1.go, you'd set PROJECT_ROOT=github.com/foo/bar.

John Asmuth
  • 1,052
  • 5
  • 7
  • I don't follow... I can set `PROJECT_ROOT` only once, but in `program1/main/main.go` I import several different packages: `my_root/program1`, `my_root/utils`, `github.com/golang/glog`, to name a few (`my_root` is the name of the overall Go package, and is the directory name of my source code), so I'm not sure what to set `PROJECT_ROOT` to. – Ismail Khan Oct 03 '17 at 09:26
  • I tried setting `PROJECT_ROOT` to: `my_root` (this should have worked, I think), `my_root/program1`, `program1`, but all resulted in the same problem. Since `my_root` is not an actual folder in my Git repo, maybe the Go build step doesn't "know" about the `my_root` directory, which messes up my paths? – Ismail Khan Oct 03 '17 at 09:33
  • (apologies for the spam, just keep getting more info to share) When I set `PROJECT_ROOT` to `my_root`, I get several errors that look like this: `cannot find package "my_root/utils" in any of` `/usr/local/go/src/my_root/utils (from $GOROOT)` `/workspace/program1/main/gopath/src/my_root/utils (from $GOPATH)` The latter error file path looks absurd to me... seems to be looking inside `program1/main/`! – Ismail Khan Oct 03 '17 at 09:50
  • never mind, I played around with the `dirs` field and it seems to work now. Thanks! – Ismail Khan Oct 03 '17 at 12:46
  • As you discovered, if you set `PROJECT_ROOT` you need to run the `gcr.io/cloud-builders/go` step from the directory containing things directly inside the root - the env var tells the builder that "this directory is the project root, and call it ". – John Asmuth Oct 04 '17 at 12:41
  • @IsmailKhan could you provide the setup you did to avoid error "cannot find package " please – John Balvin Arias Sep 18 '18 at 22:55
2

Fixed the problem (but not exactly sure how...), thanks to these changes:

  1. Set PROJECT_ROOT to my_root, such that the code I want to compile sits at my_root/program1/main/main.go (thanks to John Asmuth for his answer: https://stackoverflow.com/a/46526875/6905609)
  2. Remove the dirs field for the Go build step
  3. Set the -o flag to ./program1/main/main, and the final build arg to ./program1/main/main.go

Previously I was cding into the program1/main directory during the build step, and for some reason go build was looking for packages within my_root/program1/main instead of my_root. Weird!

Ismail Khan
  • 842
  • 2
  • 8
  • 20