A Justfile for Docker
Each new project I start ends up needing a dedicated container for CI. Some then accumulate additional containers for other CI jobs.
Remembering the commands to build and publish these containers usually became a game of grepping the shell history in search of the correct commands. After doing this too many times, I now have a Justfile to store these commands.
Just is just a command runner.
Think make without the cruft, but also without the dependency tracking. It is just a way of storing sequences of commands (called recipes) that might be useful later. Out-of-the-box it provides a useful --list command, recipe dependencies, and an easy way to parametrize recipes.
I usually create a docker/ directory in the root of the repository, and put my dockerfiles there.
<repo-root>
- justfile
- docker/
- docker.justfile
- pre-commit.dockerfile
The docker.justfile is included in the main Justfile with import "docker/docker.justfile". This helps to keep the length of main Justfile manageable.
Without further ado, here is the Justfile
#
# Top-Level Rules
#
[group("Build Docker Images")]
build-docker: \
(build-docker-pre-commit)
[group("Publish Docker Images")]
publish-docker: \
(publish-docker-pre-commit)
#
# Image-specific rules
#
[group("Build Docker Images")]
build-docker-pre-commit: (_build-docker "pre-commit")
[group("Publish Docker Images")]
publish-docker-pre-commit: \
build-docker-pre-commit \
(_publish-docker "pre-commit")
#
# Helper rules
#
GITLAB_REGISTRY_URL:= "registry.gitlab.com"
GITLAB_REGISTRY_NS := GITLAB_REGISTRY_URL + "/com_kieffer/comkieffer.com"
GIT_HASH := `git describe --always --dirty`
_build-docker image_name:
@echo "Tagging {{ image_name }} with {{ GIT_HASH }}"
docker image build \
--file docker/{{ image_name }}.dockerfile \
--tag {{ GITLAB_REGISTRY_NS }}/{{ image_name }}:{{ GIT_HASH }} \
docker/
docker image tag \
{{ GITLAB_REGISTRY_NS }}/{{ image_name }}:{{ GIT_HASH }} \
{{ GITLAB_REGISTRY_NS }}/{{ image_name }}:latest
_publish-docker image_name:
docker image push {{ GITLAB_REGISTRY_NS }}/{{ image_name }}:{{ GIT_HASH }}
docker image push {{ GITLAB_REGISTRY_NS }}/{{ image_name }}:latest
Starting from the bottom, we have a pair of rules: _build_docker, and _publish_docker. Since they start with an underscore, they are private rules, and they are not shown in the just --list output.
The _build_docker rule, takes a single argument: the name of the image (without the .dockerfile extension). This name will become the container name. Once the image is built, it receives the latest tag, as well was being tagged with the current commit short hash. This makes it easier to find out when an image was built and what it actually contains.
Make sure to edit the GITLAB_REGISTRY_NS to give the images the correct name.
The _publish_docker command just publishes the images to the registry.
These rules give us an easy way of building containers. For each container we created, we add a build-docker-<container-name> and publish-docker-<container-name> to build and publish the container.
Finally, we add these rules to the main build-docker and publish-docker rules.
In general, running just publish-docker is enough to build and publish all the images.