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
Dockerfilepresent 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
Dockerfileshall 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
Dockerfilehas 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:$hashfrom the docker registry. - If the load fails, build
docker_image_name:$hashfrom theDockerfileand 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?
Dockerfilewithout building the image on each and every commit.