dockerpodmanbuildahcontainer-image

Adding annotation/label to OCI container-image without creating the container first


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?


Solution

  • 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
        }
      ]
    }