Yet another post about reducing golang docker image build times
Yes, this is another post on how you can reduce golang docker build times.
There’s one thing that grinds my gears and that’s a long development workflow loop, a lot of posts tell you to go get a cup of coffee while something is compiling/building and i hate it. I want to get this shit done so THEN i go and get that cup of coffee. It’s very easy to lose focus of what you’re trying to accomplish if every time you say build you have to wait longer than 30s. There’s no reason to always be compiling Go packages when building the docker image when changed nothing in them and you’re just tweaking your application, so here’s a nifty trick to cut down on that.
Docker buildkit
You’ll want to be using it, as the doc says:
Docker Build enhancements for 18.09 release introduces a much-needed overhaul of the build architecture. By integrating BuildKit, users should see an improvement on performance, storage management, feature functionality, and security.
Docker images created with BuildKit can be pushed to Docker Hub just like Docker images created with legacy build the Dockerfile format that works on legacy build will also work with BuildKit builds The new –secret command line option allows the user to pass secret information for building new images with a specified Dockerfile
For that you can specify at the top of your Dockerfile
:
And when building:
Build stages
Now we can make use of docker build stages that are cached and only rebuilt if something changes, the next snippet creates the initial build stage that derives out of the stock golang:1.16
image.
Notice how only three files get copied there: go.mod
and go.sum
that contain the declaration of your dependencies and a specially generated docker_deps.go
file, when this is done we’ll have a layer
that will only get rebuilt if you add more dependencies to your project.
The only thing left to uncover now is how did this docker_deps.go
file get generated, it’s just a bit of shell script around the json output of
We also need to inject an empty main
entry point or the compiler will refuse to build and our packages won’t be compiled as well.
We can now derive a new layer out of the previous one that will have all the dependency packages already built. Only the changes to your code will get built, that will decrease by a lot your build times and your workflow will be faster.
tags: