I’m using go 1.11 with module support. I understand that the go tool now installs dependencies automatically on build/install. I also understand the reasoning.
I’m using docker to build my binaries. In many other ecosystems its common to copy over your dependency manifest (package.json, requirements.txt, etc) and install dependencies as a separate stage from build. This takes advantage of docker’s layer caching, and makes rebuilds much faster since generally code changes vastly outnumber dependency changes.
I was wondering if vgo has any way to do this?
It was an issue #26610, which is fixed now.
So now you can just use:
go mod download
For this to work you need just the
For example, here’s how to have a cached multistage Docker build:
FROM golang:1.12-alpine as builder RUN apk --no-cache add ca-certificates git WORKDIR /build/myapp # Fetch dependencies COPY go.mod ./ RUN go mod download # Build COPY . ./ RUN CGO_ENABLED=0 go build # Create final image FROM alpine WORKDIR /root COPY --from=builder /build/myapp/myapp . EXPOSE 8080 CMD ["./myapp"]
You may use the
go mod vendor command which will create a
vendor folder in the main module’s root folder, and copy all dependencies into it. After this you may pass the
-mod=vendor param to the go tool, and then dependencies from the
vendor folder will be used to build / compile / test your app.
So what you may do to speed up your builds:
- Run the
go mod vendorcommand to have an actual version of your dependencies.
- Save / cache this
- During builds, restore this
vendorfolder, and build / install your app by passing the
-mod=vendorargument to the go tool, so no dependencies will be downloaded, but the content of the
vendorfolder will be used.
go help mod:
Modules and vendoring
When using modules, the go command completely ignores vendor directories.
By default, the go command satisfies dependencies by downloading modules
from their sources and using those downloaded copies (after verification,
as described in the previous section). To allow interoperation with older
versions of Go, or to ensure that all files used for a build are stored
together in a single file tree, ‘go mod vendor’ creates a directory named
vendor in the root directory of the main module and stores there all the
packages from dependency modules that are needed to support builds and
tests of packages in the main module.
To build using the main module’s top-level vendor directory to satisfy
dependencies (disabling use of the usual network sources and local
caches), use ‘go build -mod=vendor’. Note that only the main module’s
top-level vendor directory is used; vendor directories in other locations
are still ignored.
We also make docker images for go applications and we use dind to make those images and we prepared a CI/CD image with all dependencies preinstalled to make the builds faster. Though, it took a little bit of scripting to glue everything together.
Moreover, layering up the dependencies could result in big size of docker images. I suggest try multi-stage builds which could help making images super lite.