1

I'm trying to create a dockerfile for my go server but it keeps failing as it does not recognize some local dependencies (they are modules on the code itself, not external dependencies).

example:

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()
}

Here's the error:

 => 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

Please note that this private-repo-url corresponds to this application's repository (it's not an external dependency).

Here's the 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"]

And the mod.go file:

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
)

I've read about GO111MODULE saying it should be on, and I also read that it's enabled by default from 1.17 (here).

Also according to the official docker image (in dockerhub) the right way is using go get and go install after copying all the files. This approach lead me to a slightly different problem which is that the docker can not access the repository (because it's private) and adding credentials to the docker is something I'd like to avoid.

I tried to play arround with the environment variable GOVCS setting it's value like:

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

But it still did fail with the same error.

Finally I tried with the replace, I figured that if I removed the from the local dependencies it would work, so I executed (inside the Dockerfile) this:

RUN go mod edit -replace <private-repo-url>=./

Again it did fail with:

 => 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

Is there any way to prevent go builder/package installer to look for these files externally? As both go mod and go get + go install try to access this private repository and fail as they do not have access. But they should not try to access it on the first place as it's the application's repository... Or is that I'm doing something wrong (clearly or I wouldn't be here), missing something?

Juan
  • 117
  • 15
  • Where is the package `/src/cmd/http-api/bootstrap`? If it's not in the same repository then `go build` has to try and get it. Also try fully qualifying the package you are building as the last argument to `go build`; I can't tell where your main package is located relative to your `go.mod`. – Zyl Dec 02 '21 at 22:09
  • 2
    https://go.dev/doc/tutorial/ talks about how to successfully use `replace` in this situation – erik258 Dec 02 '21 at 22:15
  • The issue was as pointed out in an other comment that ```ADD ./src .``` did not maintain the src folder, which was referenced on the dependency imports, that was the reason those dependencies were not found locally and the build process did try to fetch them from the repository. – Juan Dec 03 '21 at 01:03

1 Answers1

3

ADD ./src . - that copies the contents of src to the current folder, stripping away the src part.

It should just be COPY . ./

Also note that it's not recommended to have a src subfolder in your source tree - the folder that contains go.mod is already the source tree.

rustyx
  • 80,671
  • 25
  • 200
  • 267
  • It did work! I spend literally hours on this and it was way this simple. Thanks a lot! Regarding not having a src folder, we were planning to use it to have the source separated from the other files included in the repository like the CI config, k8s, etc. is there a better approach to address this? – Juan Dec 03 '21 at 01:01
  • It's not a problem for Go to have config files stored together with Go sources. For this reason people usually just don't separate them. What is useful though is to have a multistage build in order to exclude Go SDK and project sources from the final image. See [this answer](https://stackoverflow.com/a/56693289/485343) for more details on that. – rustyx Dec 03 '21 at 10:21