For adding some annotations/labels to a image, we first have to create the container from the image, and then we can add some annotations/labels using buildah-config: buildah-config [options] containerID
But this requires first creating a container from image, then adding the required annotation/label, and then committing the changes back to an image.
But creating a container just for making some small change to the image configuration seems a unnecessary step which would take additional time and memory.
Is there a better way to add annotations/labels to a image?
For an image on a registry (or in an OCI Layout structure on the filesystem) there are various tools to modify that image. From go-containerregistry (by Google), there's crane mutate
:
$ crane mutate --help
Modify image labels and annotations. The container must be pushed to a registry, and the manifest is updated there.
Usage:
crane mutate [flags]
Flags:
-a, --annotation stringToString New annotations to add (default [])
--append strings Path to tarball to append to image
--cmd strings New cmd to set
--entrypoint strings New entrypoint to set
-e, --env stringToString New envvar to add (default [])
-h, --help help for mutate
-l, --label stringToString New labels to add (default [])
-t, --tag string New tag to apply to mutated image. If not provided, push by digest to the original image repository.
Global Flags:
--insecure Allow image references to be fetched without TLS
--platform platform Specifies the platform in the form os/arch[/variant][:osversion] (e.g. linux/amd64). (default all)
-v, --verbose Enable debug logs
And from regclient (by myself), there's regctl image mod
:
$ regctl image mod --help
EXPERIMENTAL: Applies requested modifications to an image
Usage:
regctl image mod <image_ref> [flags]
Flags:
--annotation stringArray set an annotation (name=value) (default )
--annotation-base stringArray set base image annotations (image/name:tag,sha256:digest) (default )
--buildarg-rm string delete a build arg (default "")
--buildarg-rm-regex string delete a build arg with a regex value (default "")
--config-time-max string max timestamp for a config (default "")
--create string Create tag
--data-max stringArray sets or removes descriptor data field (size in bytes) (default )
--expose-add stringArray add an exposed port (default )
--expose-rm stringArray delete an exposed port (default )
--external-urls-rm remove external url references from layers (first copy image with "--include-external") (default )
--file-tar-time-max stringArray max timestamp for contents of a tar file within a layer (default )
-h, --help help for mod
--label stringArray set an label (name=value) (default )
--label-to-annotation set annotations from labels (default )
--layer-rm-created-by string delete a layer based on history (created by string is a regex) (default "")
--layer-rm-index uint delete a layer from an image (index begins at 0) (default )
--layer-strip-file string delete a file or directory from all layers (default "")
--layer-time-max string max timestamp for a layer (default "")
--rebase rebase an image using OCI annotations (default )
--rebase-ref string rebase an image with base references (base:old,base:new) (default "")
--replace Replace tag (ignored when "create" is used)
--time-max string max timestamp for both the config and layers (default "")
--to-oci convert to OCI media types (default )
--volume-add stringArray add a volume definition (default )
--volume-rm stringArray delete a volume definition (default )
Global Flags:
--logopt stringArray Log options
--user-agent string Override user agent
-v, --verbosity string Log level (debug, info, warn, error, fatal, panic) (default "warning")
For example:
$ regctl manifest get localhost:5000/library/alpine:latest
Name: localhost:5000/library/alpine:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad
Manifests:
Name: localhost:5000/library/alpine:latest@sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870
Digest: sha256:1304f174557314a7ed9eddb4eab12fed12cb0cd9809e4c28f29af86979a3c870
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Name: localhost:5000/library/alpine:latest@sha256:5da989a9a3a08357bc7c00bd46c3ed782e1aeefc833e0049e6834ec1dcad8a42
Digest: sha256:5da989a9a3a08357bc7c00bd46c3ed782e1aeefc833e0049e6834ec1dcad8a42
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v6
Name: localhost:5000/library/alpine:latest@sha256:0c673ee68853a04014c0c623ba5ee21ee700e1d71f7ac1160ddb2e31c6fdbb18
Digest: sha256:0c673ee68853a04014c0c623ba5ee21ee700e1d71f7ac1160ddb2e31c6fdbb18
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
Name: localhost:5000/library/alpine:latest@sha256:ed73e2bee79b3428995b16fce4221fc715a849152f364929cdccdc83db5f3d5c
Digest: sha256:ed73e2bee79b3428995b16fce4221fc715a849152f364929cdccdc83db5f3d5c
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: localhost:5000/library/alpine:latest@sha256:1d96e60e5270815238e999aed0ae61d22ac6f5e5f976054b24796d0e0158b39c
Digest: sha256:1d96e60e5270815238e999aed0ae61d22ac6f5e5f976054b24796d0e0158b39c
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/386
Name: localhost:5000/library/alpine:latest@sha256:fa30af02cc8c339dd7ffecb0703cd4a3db175e56875c413464c5ba46821253a8
Digest: sha256:fa30af02cc8c339dd7ffecb0703cd4a3db175e56875c413464c5ba46821253a8
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/ppc64le
Name: localhost:5000/library/alpine:latest@sha256:c2046a6c3d2db4f75bfb8062607cc8ff47896f2d683b7f18fe6b6cf368af3c60
Digest: sha256:c2046a6c3d2db4f75bfb8062607cc8ff47896f2d683b7f18fe6b6cf368af3c60
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/s390x
$ regctl image config localhost:5000/library/alpine:latest
{
"created": "2022-08-09T17:19:53.47374331Z",
"architecture": "amd64",
"os": "linux",
"config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
]
},
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:994393dc58e7931862558d06e46aa2bb17487044f670f310dffe1d24e4d1eec7"
]
},
"history": [
{
"created": "2022-08-09T17:19:53.274069586Z",
"created_by": "/bin/sh -c #(nop) ADD file:2a949686d9886ac7c10582a6c29116fd29d3077d02755e87e111870d63607725 in / "
},
{
"created": "2022-08-09T17:19:53.47374331Z",
"created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
"empty_layer": true
}
]
}
$ regctl image mod localhost:5000/library/alpine:latest \
--create mod --to-oci \
--annotation new.annotation=value \
--label some.label=1234
localhost:5000/library/alpine:mod
$ regctl manifest get localhost:5000/library/alpine:mod
Name: localhost:5000/library/alpine:mod
MediaType: application/vnd.oci.image.index.v1+json
Digest: sha256:5e1e3ed73857b08895477418bdd2b73cc9536886d84d98ef986eacca08e100ea
Annotations:
new.annotation: value
Manifests:
Name: localhost:5000/library/alpine:mod@sha256:f457cc17d630de3464ee3cd796fe83527a3daf3d1d28f710ed65b7162c29a632
Digest: sha256:f457cc17d630de3464ee3cd796fe83527a3daf3d1d28f710ed65b7162c29a632
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/amd64
Name: localhost:5000/library/alpine:mod@sha256:a442ff642289b8b9a4268451c29fc7ce8f3685ba08b32adb1fd9ddd36b4f46e4
Digest: sha256:a442ff642289b8b9a4268451c29fc7ce8f3685ba08b32adb1fd9ddd36b4f46e4
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/arm/v6
Name: localhost:5000/library/alpine:mod@sha256:003520fdc1749c2bd2d49781b24ae6937a219576541d20754124c24467e75ffc
Digest: sha256:003520fdc1749c2bd2d49781b24ae6937a219576541d20754124c24467e75ffc
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/arm/v7
Name: localhost:5000/library/alpine:mod@sha256:624a37e9b645a5286db52b2a8536f43bb64e0352fa10e847f4f049b4773046fc
Digest: sha256:624a37e9b645a5286db52b2a8536f43bb64e0352fa10e847f4f049b4773046fc
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/arm64
Name: localhost:5000/library/alpine:mod@sha256:9fbcc84ca534fa1d3b0047226860e39321da082615bdef03946edd5225952217
Digest: sha256:9fbcc84ca534fa1d3b0047226860e39321da082615bdef03946edd5225952217
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/386
Name: localhost:5000/library/alpine:mod@sha256:08246b80173b3ace4446aca1e26406d1cef1eaea29126ab3ebe964e0fbba4dd9
Digest: sha256:08246b80173b3ace4446aca1e26406d1cef1eaea29126ab3ebe964e0fbba4dd9
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/ppc64le
Name: localhost:5000/library/alpine:mod@sha256:945b2dab97c5518c276e53df551871ec089736f3abc7fe62003923b04ed9bcb5
Digest: sha256:945b2dab97c5518c276e53df551871ec089736f3abc7fe62003923b04ed9bcb5
MediaType: application/vnd.oci.image.manifest.v1+json
Platform: linux/s390x
$ regctl image config localhost:5000/library/alpine:mod
{
"created": "2022-08-09T17:19:53.47374331Z",
"architecture": "amd64",
"os": "linux",
"config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
],
"Labels": {
"some.label": "1234"
}
},
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:994393dc58e7931862558d06e46aa2bb17487044f670f310dffe1d24e4d1eec7"
]
},
"history": [
{
"created": "2022-08-09T17:19:53.274069586Z",
"created_by": "/bin/sh -c #(nop) ADD file:2a949686d9886ac7c10582a6c29116fd29d3077d02755e87e111870d63607725 in / "
},
{
"created": "2022-08-09T17:19:53.47374331Z",
"created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
"empty_layer": true
}
]
}