As someone who loves go, and uses docker as their primary build mechanism, Pierre's article The Go Dockerfile was very appealing to me. In recent times, I've been using alpine as my base image for go programs out of convenience. Prior to this article I wasn't familiar Docker's ability to do multi-stage builds, so this provided a good learning opportunity. I had 2 differences to his method though, which I had to resolve before being able to use this build system.
I don't really have strong opinions about go dependency management, but I've used glide since I started working with go. Going with a tried-and-true installation method, the first few lines of the Dockerfile are straightforward:
FROM golang:1.10 AS builder ADD https://github.com/Masterminds/glide/releases/download/v0.13.1/glide-v0.13.1-linux-amd64.tar.gz . RUN tar -xvf glide-v0.13.1-linux-amd64.tar.gz && \ cp linux-amd64/glide /go/bin/ && \ rm -rf linux-amd64
The fact that go programs end up being a single statically linked binary makes this easy. The next few steps should be pretty close to identical to the original article.
WORKDIR $GOPATH/src/github.com/project/repo COPY . ./ RUN glide up RUN env CGO_ENABLED=0 go build
One caveat to this, make sure you have
vendor/ in your
The first time I went to build this way, I was accidentally successful because my dependencies were already vendored,
and glide was basically a no-op.
The last few lines of the Dockerfile define our actual container to be deployed:
FROM scratch ENV PORT 8080 COPY --from=builder /go/src/github.com/project/repo/binary ./ COPY www/ www/ CMD ["./binary"]
The only real difference here is the extra
When deploying APIs with Go, I typically have them self-host a swagger UI page or something along those lines.
That means I need a way to bundle some minimal HTML/CSS along with the binary itself.
One of the conveniences from Alpine is the presence of
so building a container with some pathing is a little easier.
But having the builder do a little extra file shuffling means we can have a smaller, simpler final image.
So what does the final image look like?
18MB in total, of which 16MB is the go binary itself.
And I finally manage to join the
FROM scratch club :D
Thanks to the gophers project for the free gopher images.