Given a repository containing a Dockerfile
that defines the build environment used by the CI pipeline as well as by the developer (e.g. as a Visual Studio Code devcontainer), the CI pipeline shall fulfill the following requirements:
- The CI pipeline shall build the repository's contents in the context of a docker image built from the very
Dockerfile
present in the working branch (or the result of its merge to the target branch where applicable in the context of a pull request).
- Rationale: Builds shall be deterministic so that old repository versions shall be built with their original docker image, not with the newest one.
- Rationale: Changes to the
Dockerfile
shall be considered automatically without the need for manual user intervention (i.e. local docker build followed by a manual push).
- The CI pipeline shall reuse an already built docker image if the applicable
Dockerfile
has already been "baked" into such an image pushed to the registry.
- Rationale: Building a docker image on each commit is resource-consuming (time, energy).
I couldn't find an existing best practice to implement that out of the box (my CI environment being Azure DevOps Pipelines if it matters) so I came with the following concept:
- Calculate the
Dockerfile
's hash. - Load
docker_image_name:$hash
from the docker registry. - If the load fails, build
docker_image_name:$hash
from theDockerfile
and push it to the docker registry. - Use
docker_image_name:$hash
(from the registry / from the local cache) to run the CI pipeline (using Azure's container jobs in my case).
Questions:
- Does this procedure make sense as a solution to my use case?
- I can't imagine being the first to realize this use case. Is there an existing mechanism (as part of the docker utilities, as part of the Azure DevOps Pipelines framework or from something completely different) that fulfills my needs?