Tags and manifests#
The main purpose of the source code in the tagging folder is to
properly write tags file, build history line and manifest for a single-platform image,
apply these tags, and then merge single-platform images into one multi-arch image.
What is a tag and a manifest#
A tag is a label attached to a Docker image identifying specific attributes or versions.
For example, an image jupyter/base-notebook with Python 3.10.5 will have a full image name quay.io/jupyter/base-notebook:python-3.10.5.
These tags are pushed to our Quay.io registry.
A manifest is a description of important image attributes written in Markdown format.
For example, we dump all conda packages with their versions into the manifest.
Main principles#
All images are organized in a hierarchical tree. More info on image relationships.
TaggerInterfaceandManifestInterfaceare interfaces for functions to generate tags and manifest pieces by running commands in Docker containers.Tags and manifests are reevaluated for each image in the hierarchy since values may change between parent and child images.
To tag an image and create its manifest and build history line, run
make hook/<somestack>(e.g.,make hook/base-notebook).
Utils#
DockerRunner#
DockerRunner is a helper class to easily run a docker container and execute commands inside this container:
from tagging.utils.docker_runner import DockerRunner
with DockerRunner("ubuntu") as container:
DockerRunner.exec_cmd(container, cmd="env")
GitHelper#
GitHelper methods are run in the current git repo and give the information about the last commit hash and commit message:
from tagging.utils.git_helper import GitHelper
print("Git hash:", GitHelper.commit_hash())
print("Git message:", GitHelper.commit_message())
The prefix of commit hash (namely, 12 letters) is used as an image tag to make it easy to inherit from a fixed version of a docker image.
Taggers and Manifests#
Tagger#
Tagger is a function that runs commands inside a docker container to calculate a tag for an image.
All the taggers follow TaggerInterface:
TaggerInterface = Callable[[Container], str]
So, the tagger(container) gets a docker container as an input and returns a tag.
For example:
def commit_sha_tagger(container: Container) -> str:
return GitHelper.commit_hash_tag()
taggers/subdirectory contains all taggers.apps/write_tags_file.py,apps/apply_tags.py, andapps/merge_tags.pyare Python executables used to write tags for an image, apply tags from a file, and create multi-arch images.
Manifest#
All manifest functions except build_info_manifest follow ManifestInterface
and manifest(container) method returns a piece of the manifest.
ManifestInterface = Callable[[Container], MarkdownPiece]
For example:
def apt_packages_manifest(container: Container) -> MarkdownPiece:
return MarkdownPiece(
title="## Apt Packages",
sections=[quoted_output(container, "apt list --installed")],
)
where:
quoted_output(container, cmd)simply runs the command inside a container usingDockerRunner.exec_cmdand wraps it to triple quotes to create a valid markdown piece. It also adds the command which was run to the markdown piece.manifests/subdirectory contains all the manifests.apps/write_manifest.pyis a Python executable to create the build manifest and history line for an image.
Images Hierarchy#
All images’ dependencies on each other and what taggers and manifests are applicable to them are defined in hierarchy/images_hierarchy.py.
hierarchy/get_taggers.py and hierarchy/get_manifests.py define functions to get the taggers and manifests for a specific image.