Build Docker image for site builds that allow for separately configurable Hugo and Go versions
The Technical Writing team maintains a "site building" Docker image that's configured at: https://gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/-/blob/main/dockerfiles/docs-gitlab-com-builder.Dockerfile?ref_type=heads.
At the moment, we can only specify a version of Hugo, with the version of every other dependency set by the upstream maintainers of the base Docker image we build from. This seemed ok at the time because we were far more concerned about pinning Hugo versions than Go versions.
However, this reduces our ability to move forward with other dependencies while being able to be extra conservative with Hugo dependencies. This doesn't seem like very much of a problem, but does block issues like !1136 (merged). We try in this project to keep our dependencies aligned with dependencies in other projects. Many projects have moved to Go 1.24:
- https://gitlab.com/gitlab-org/gitlab-runner/-/blob/e701d4bdead7d68e8addc225ec7427358f1301b5/.tool-versions#L2
- https://gitlab.com/gitlab-org/gitaly/-/blob/1623ba9b50fe33532f1ed3bbd3c566337195cedb/.tool-versions#L2
- https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/3f1b9d04992add17b7cedadf390c996cd1a9b4ab/.tool-versions#L37
Even in this project, we locally use Go 1.24: https://gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/-/blob/b3b8a0efcc6afefd57116ddd4642da6d0c1184e0/mise.toml#L8. It's only in our site builds that we're stuck with Go 1.23:
- Run
docker run --rm -ti registry.gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/docs-gitlab-com-builder:hugo-0.145.0 sh. - In the running container:
/src # go version go version go1.23.8 linux/amd64
Proposal
I propose that we refactor the builder Docker image so that it can be tagged with independent versions for:
- Go
- Hugo
- Node
So images would be tagged:
- Rather than:
registry.gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/docs-gitlab-com-builder:hugo-0.145.0 - Would now be:
registry.gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/docs-gitlab-com-builder:go-1.24-hugo-0.145.0-nodejs-22
As now, these versions would be derived from settings in .gitlab-ci.yml: https://gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/-/blob/b3b8a0efcc6afefd57116ddd4642da6d0c1184e0/.gitlab-ci.yml#L16.
The process for building an image would be exactly the same, and the functionality of the image would be exactly the same.
Using mise
One was to achieve this is to build the image using a more basic image, and pulling the tooling directly from each project.
Another possible way is to introduce mise into the Docker image as an installation and execution method. We wouldn't try and reuse the mise.toml file in the project, but rather use mise to install dependencies with the versions we pin at build time.
For example, with a basic image that's had mise installed, installation could be:
-
mise --quiet use --global --pin go@${GO_VERSION}for Go. -
mise --quiet use --global --pin hugo-extended@${HUGO_VERSION_NEXT}for Hugo. -
mise --quiet use --global --pin node@${NODE_VERSION}for Node.js.
Some guidance for running mise in pipelines is available at: https://mise.jdx.dev/continuous-integration.html, but I'm sure we could also work with mise very similarly to how we work with it locally.