I'm working on a go project, using vgo, with a Dockerfile, and I'd like docker to cache the dependencies of the project such that it has two properties:
go.mod
file changes, the dependencies will be re-downloadedgo.mod
, the dependencies will not be re-downloaded.Right now, I do:
...
RUN go get -u golang.org/x/vgo
COPY . /go/src/whatever
RUN vgo install
...
But if you change a go file, the dockerfile will have to be rebuilt from the COPY
layer onwards.
What I'd like, in short, is to do:
...
RUN go get -u golang.org/x/vgo
COPY go.mod /go/src/whatever
RUN vgo install_dependencies
COPY . /go/src/whatever
RUN vgo install
...
That way, if I change go.mod
, all the dependencies will be downloaded and rebuilt, but otherwise, we can proceed right to building the binary.
I can see a couple of ways to get behavior like this, but all of them have drawbacks:
$GOPATH/src/mod
into the docker container, but that's going to have lots of files I don't needvgo mod -vendor
before I build the docker container, and copy the vendor directory, but that relies on the developer to remember to run vgo mod -vendor
every time that go.mod
changes, otherwise the app won't build and they'll have to run vgo mod -vendor
before retrying the docker build.Can you think of a way for me to get behavior like my imaginary vgo install_dependencies
? Am I missing a vgo trick to do so?
tl;dr: In current go master and in future go releases, go mod download
will do this job. For now you need a hack.
On the gophers slack, I was referred to this issue: https://github.com/golang/go/issues/26610 where I learned that this would do more or less what I want (assuming here that you're using go version 1.11beta3):
# Populate the module cache based on the go.{mod,sum} files.
COPY go.mod .
COPY go.sum .
RUN go list -e $(go list -f '{{.Path}}' -m all)
Later in the thread, Russ Cox implements go mod download
, which will be available in the next release of go
, allowing me to remove the silly go list
hack above.
update: go mod download
is now widely available and you should use it on go 1.12 and later