Acerca de los resúmenes de imágenes de contenedor


En este documento, se describen los resúmenes de imágenes, lo que incluye qué son, cómo encontrarlos y cómo imponer su uso en clústeres de Kubernetes. Este documento está dirigido a desarrolladores y operadores que compilan y, además, implementan imágenes de contenedor.

El resumen de una imagen de contenedor identifica de forma única y no intencional la imagen de un contenedor. Cuando implementas imágenes por resumen, evitas los inconvenientes de la implementación mediante etiquetas de imagen.

Para usar los comandos de este documento, necesitas acceso a un entorno de shell en Linux o macOS con herramientas como la CLI de Cloud, Docker, cURL jq y pack ya instaladas. También puedes usar Cloud Shell, que tiene preinstaladas estas herramientas.

Imágenes de contenedor y etiquetas de imagen

Cuando trabajas con imágenes de contenedor, necesitas una forma de referirte a las imágenes que usas. Las etiquetas de imagen son una forma común de hacer referencia a las diferentes revisiones de una imagen. Un enfoque común es etiquetar imágenes con un identificador de versión en el momento de la compilación. Por ejemplo, v1.0.1 podría hacer referencia a una versión que denomines 1.0.1.

Las etiquetas facilitan la búsqueda de revisiones de imágenes mediante strings legibles. Sin embargo, las etiquetas son referencias mutables, lo que significa que la imagen a la que hace referencia una etiqueta puede cambiar, como se ilustra en el siguiente diagrama:

Etiqueta de imagen que apunta a una imagen desactualizada.

Como se muestra en el diagrama anterior, si publicas una imagen nueva con la misma etiqueta de una imagen existente, la etiqueta deja de referirse a la imagen existente y comienza a aludir a tu imagen nueva.

Desventajas de las etiquetas de imagen

Debido a que las etiquetas son mutables, presentan las siguientes desventajas cuando las usas para implementar una imagen:

  • En Kubernetes, la implementación mediante etiquetas puede producir resultados inesperados. Por ejemplo, supongamos que tienes un recurso de implementación existente que hace referencia a una imagen de contenedor mediante la etiqueta v1.0.1. Para corregir un error o hacer un cambio pequeño, el proceso de compilación crea una imagen nueva con la misma etiqueta v1.0.1. Los pods nuevos que se crean a partir de tu recurso de implementación pueden terminar usando la imagen antigua o la nueva, incluso si no cambias las especificaciones del recurso. Este problema también se aplica a otros recursos de Kubernetes, como StatefulSets, DaemonSets, ReplicaSets y Jobs.

  • Si usas herramientas para leer o analizar imágenes, sus resultados solo serán válidos para la imagen que se leyó. Para asegurarte de implementar la imagen que se leyó, no puedes confiar en la etiqueta porque es posible que la imagen a la que se refiera haya cambiado.

  • Si usas la autorización binaria con Google Kubernetes Engine (GKE), no se permite la implementación basada en etiquetas porque es imposible determinarlo qué imagen se usó cuando se creó un Pod.

Cuando implementas tus imágenes, puedes usar un resumen de imágenes para evitar las desventajas de usar etiquetas. Puedes agregar etiquetas a tus imágenes si lo deseas, pero no es necesario que lo hagas.

Estructura de una imagen

Una imagen tiene los siguientes componentes:

Estos componentes se ilustran en el siguiente diagrama:

Los componentes de una imagen. Se muestran los detalles de un manifiesto de imagen, un objeto de configuración, las capas de sistema de archivos y un índice de imagen.

En la imagen anterior, se muestra información adicional sobre los componentes de la imagen:

  • El manifiesto de la imagen es un documento JSON que contiene una referencia para el objeto de configuración, las capas del sistema de archivos y los metadatos opcionales.
  • El manifiesto de imagen hace referencia al objeto de configuración y a cada una de las capas del sistema de archivos mediante los atributos digest. El valor de un atributo digest es un hash criptográfico del contenido al que se refiere el resumen, que generalmente se calcula mediante el algoritmo SHA-256.
  • Los valores de resumen se usan para construir direcciones inmutables para los objetos. Este proceso se denomina almacenamiento direccionado por el contenido y significa que puedes recuperar manifiestos de imágenes, índices de imágenes, objetos de configuración y capas según sus resúmenes.
  • El resumen de la imagen es el hash del índice de la imagen o el documento JSON del manifiesto de la imagen.
  • El objeto de configuración es un documento JSON que define propiedades de la imagen, como la arquitectura de CPU, el punto de entrada, los puertos expuestos y las variables de entorno.
  • El arreglo de capas del sistema de archivos define el orden que el entorno de ejecución del contenedor usa para apilar las capas. Las capas se distribuyen como archivos tar, que, por lo general, se comprimen con la utilidad gzip.
  • El índice de imagen opcional, a veces denominado lista de manifiestos, hace referencia a uno o más manifiestos de imágenes. La referencia es el resumen del manifiesto de la imagen. Un índice de imagen es útil cuando produces varias imágenes relacionadas para diferentes plataformas, como las arquitecturas amd64 y arm64.

Para obtener más información, consulta la sección Cómo explorar manifiestos de imágenes, resúmenes y etiquetas.

Busca resúmenes de imágenes

Si quieres usar resúmenes de imágenes para la implementación, primero debes encontrar el resumen. Luego, puedes usar el resumen con el comando de implementación o incluirlo en tus manifiestos de Kubernetes.

Puedes obtener el resumen de una imagen de diferentes maneras, según tu situación actual. En las siguientes secciones, se incluyen ejemplos de diferentes productos y herramientas.

En las siguientes secciones, ejecuta los comandos en Cloud Shell o en un entorno de shell con herramientas, como la CLI de gcloud, Docker, cURL y jq ya instalados.

Artifact Registry

Container Registry

  • Para las imágenes almacenadas en Container Registry, puedes usar el comando gcloud container images describe y proporcionar el nombre y una etiqueta a fin de obtener el resumen de una imagen. Usa la marca --format para mostrar solo el resumen:

    gcloud container images describe \
        gcr.io/google-containers/pause-amd64:3.2 \
        --format 'value(image_summary.digest)'
    

    El resultado es similar al siguiente, aunque el valor de tu resumen puede ser distinto:

    sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    

Cloud Build

En el caso de las imágenes compiladas con Cloud Build, puedes obtener el resumen de imágenes usando el comando gcloud builds describe con la marca --format. Este enfoque funciona independientemente del registro que usaste para publicar tu imagen.

  • En el caso de una compilación que ya se completó, haz lo siguiente:

    1. Obtén una lista de compilaciones para tu proyecto:

      gcloud builds list
      

      Anota un BUILD_ID.

    2. Obtén el resumen de imágenes:

      gcloud builds describe BUILD_ID \
          --format 'value(results.images[0].digest)'
      

      Reemplaza BUILD_ID por el ID único que Cloud Build asignó a tu compilación.

  • Obtén el nombre y el resumen de la imagen de la compilación más reciente de Cloud Build para tu proyecto actual:

    gcloud builds describe \
        $(gcloud builds list --limit 1 --format 'value(id)') \
        --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'
    
  • Si tu compilación produjo varias imágenes, filtra el resultado y obtén el resumen de una de las imágenes:

    gcloud builds describe BUILD_ID --format json \
        | jq -r '.results.images[] | select(.name=="YOUR_IMAGE_NAME") | .digest'
    

    Reemplaza YOUR_IMAGE_NAME por el nombre de una de las imágenes de tu archivo cloudbuild.yaml.

  • Si envías una compilación a Cloud Build con el comando gcloud builds submit, puedes capturar el resumen de la imagen del resultado en una variable de entorno:

    IMAGE_DIGEST=$(gcloud builds submit \
        --format 'value(results.images[0].digest)' | tail -n1)
    

Cloud Native Buildpacks

  • Si usas Cloud Native Buildpacks y el compilador de Google Cloud para compilar y publicar imágenes, puedes capturar el nombre de la imagen y el resumen mediante la marca --quiet con el comando pack:

    pack build --builder gcr.io/buildpacks/builder:v1 --publish --quiet \
        LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE \
        > image-with-digest.txt
    

    Reemplaza lo siguiente:

    El archivo image-with-digest.txt contiene el nombre y el resumen de la imagen.

    Usa la marca --tag si deseas agregar etiquetas a la imagen.

Cliente de Docker

  • El subcomando manifest del cliente de línea de comandos de docker puede recuperar los manifiestos de imágenes y las listas de manifiestos de los registros de imágenes de contenedor.

    Obtén el resumen de la lista de manifiestos de la imagen registry.k8s.io/pause:3.9 para la arquitectura de la CPU amd64 y el sistema operativo linux:

    docker manifest inspect --verbose registry.k8s.io/pause:3.9 | \
        jq -r 'if type=="object"
            then .Descriptor.digest
            else .[] | select(.Descriptor.platform.architecture=="amd64" and
            .Descriptor.platform.os=="linux") | .Descriptor.digest
            end'
    

    El resultado es similar al siguiente:

    sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10
    
  • Para las imágenes que se almacenan en tu daemon de Docker local y que se extrajeron de un registro de imágenes o se enviaron a uno, puedes usar la herramienta de línea de comandos de Docker para lo siguiente: obtén el resumen de la imagen:

    1. Extrae la imagen a tu daemon de Docker local:

      docker pull docker.io/library/debian:bookworm
      
    2. Obtén el resumen de imágenes:

      docker inspect docker.io/library/debian:bookworm \
          | jq -r '.[0].RepoDigests[0]' \
          | cut -d'@' -f2
      

      El resultado es similar al siguiente, aunque el valor de tu resumen puede ser distinto:

      sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
      
  • Enumera todas las imágenes y todos los resúmenes de tu daemon de Docker local:

    docker images --digests
    

    El resultado muestra los resúmenes de las imágenes que tienen un valor de resumen. Las imágenes solo tienen un valor de resumen si se extrajeron de un registro de imágenes o se enviaron a uno.

crane y gcrane

Puedes usar las herramientas de línea de comandos de código abierto de crane y gcrane para obtener el resumen de una imagen sin tener que extraer la imagen a un daemon de Docker local.

  1. Descarga crane y gcrane en tu directorio actual:

    VERSION=$(curl -sL https://api.github.com/repos/google/go-containerregistry/releases/latest | jq -r .tag_name)
    curl -L "https://github.com/google/go-containerregistry/releases/download/${VERSION}/go-containerregistry_$(uname -s)_$(uname -m).tar.gz" | tar -zxf - crane gcrane
    
  2. Obtén resúmenes de imágenes:

    ./gcrane digest gcr.io/distroless/static-debian11:nonroot
    

    crane y gcrane tienen otras funciones que no se incluyen en este documento. Para obtener más información, consulta la documentación de crane y gcrane.

Impón el uso de los resúmenes de imágenes en las implementaciones de Kubernetes

Si quieres imponer el uso de los resúmenes de imágenes que implementas en tus clústeres de Kubernetes, puedes usar el controlador de políticas o Open Policy Agent (OPA) Gatekeeper. Policy Controller se compila a partir del proyecto de código abierto Gatekeeper.

Policy Controller y OPA Gatekeeper usan el motor de políticas de OPA. Policy Controller y OPA Gatekeeper proporcionan un webhook de admisión y validación de Kubernetes para aplicar políticas y definiciones de recursos personalizados (CRD) para plantillas de restricciones y restricciones.

Las plantillas de restricciones contienen una lógica de política que se expresa mediante un lenguaje declarativo de alto nivel llamado Rego. La siguiente es una plantilla de restricciones que valida que los contenedores, los contenedores init y los contenedores efímeros de una especificación de recursos de Kubernetes usen imágenes. con resúmenes:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8simagedigests
  annotations:
    metadata.gatekeeper.sh/title: "Image Digests"
    metadata.gatekeeper.sh/version: 1.0.0
    description: >-
      Requires container images to contain a digest.

      https://kubernetes.io/docs/concepts/containers/images/
spec:
  crd:
    spec:
      names:
        kind: K8sImageDigests
      validation:
        openAPIV3Schema:
          type: object
          description: >-
            Requires container images to contain a digest.

            https://kubernetes.io/docs/concepts/containers/images/
          properties:
            exemptImages:
              description: >-
                Any container that uses an image that matches an entry in this list will be excluded
                from enforcement. Prefix-matching can be signified with `*`. For example: `my-image-*`.

                It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name)
                in order to avoid unexpectedly exempting images from an untrusted repository.
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8simagedigests

        import data.lib.exempt_container.is_exempt

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not is_exempt(container)
          satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
          not all(satisfied)
          msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          not is_exempt(container)
          satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
          not all(satisfied)
          msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.ephemeralContainers[_]
          not is_exempt(container)
          satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
          not all(satisfied)
          msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image])
        }
      libs:
        - |
          package lib.exempt_container

          is_exempt(container) {
              exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", [])
              img := container.image
              exemption := exempt_images[_]
              _matches_exemption(img, exemption)
          }

          _matches_exemption(img, exemption) {
              not endswith(exemption, "*")
              exemption == img
          }

          _matches_exemption(img, exemption) {
              endswith(exemption, "*")
              prefix := trim_suffix(exemption, "*")
              startswith(img, prefix)
          }

La política anterior contiene una expresión regular como entrada para la función re_match. Esta expresión regular coincide con el resumen de la imagen del contenedor y se basa en el formato de resumen de las especificaciones de las imágenes de Open Container Initiative.

Las restricciones aplican la política a los recursos de Kubernetes mediante coincidencias con atributos como kind y namespace. La siguiente restricción de ejemplo aplica la política desde la plantilla de restricciones a todos los recursos Pod del espacio de nombres default.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sImageDigests
metadata:
  name: container-image-must-have-digest
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "default"

Después de crear la plantilla de restricciones y la restricción, cualquier Pod nuevo en el espacio de nombres default debe usar resúmenes de imágenes para hacer referencia a imágenes de contenedor.

Para ver el ejemplo completo, consulta la política imagedigests en la biblioteca de políticas de Gatekeeper.

Información sobre manifiestos de imágenes, resúmenes y etiquetas

En esta sección, aprenderás a explorar imágenes existentes en registros con herramientas de línea de comandos, como curl y docker. Ejecuta los comandos en Cloud Shell o en un entorno de shell con herramientas, como la CLI de gcloud, Docker, cURL y jq ya instalados. Los siguientes comandos usan imágenes públicas en Container Registry.

  • Obtén el manifiesto de la imagen gcr.io/google-containers/pause-amd64:3.2 con cURL y la URL del manifiesto:

    curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2
    

    El resultado es similar al siguiente:

    {
       "schemaVersion": 2,
       "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
       "config": {
          "mediaType": "application/vnd.docker.container.image.v1+json",
          "size": 759,
          "digest": "sha256:80d28bedfe5dec59da9ebf8e6260224ac9008ab5c11dbbe16ee3ba3e4439ac2c"
       },
       "layers": [
          {
             "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
             "size": 296534,
             "digest": "sha256:c74f8866df097496217c9f15efe8f8d3db05d19d678a02d01cc7eaed520bb136"
          }
       ]
    }
    

    La sección config tiene un atributo de resumen y puedes usar este valor para recuperar el objeto de configuración. Del mismo modo, cada capa tiene un atributo digest que puedes usar para recuperar el archivo tar de esa capa.

  • Si la imagen incluye el índice de imagen opcional, una solicitud GET HTTP a la URL del manifiesto mediante una etiqueta mostrará el índice de la imagen en lugar del manifiesto.

    Obtén el índice de imagen de la imagen gcr.io/google-containers/pause:3.2:

    curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2
    

    El resultado es similar a este:

    {
       "schemaVersion": 2,
       "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
       "manifests": [
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 526,
             "digest": "sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108",
             "platform": {
                "architecture": "amd64",
                "os": "linux"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 526,
             "digest": "sha256:bbb7780ca6592cfc98e601f2a5e94bbf748a232f9116518643905aa30fc01642",
             "platform": {
                "architecture": "arm",
                "os": "linux",
                "variant": "v7"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 526,
             "digest": "sha256:31d3efd12022ffeffb3146bc10ae8beb890c80ed2f07363515580add7ed47636",
             "platform": {
                "architecture": "arm64",
                "os": "linux"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 526,
             "digest": "sha256:7f82fecd72730a6aeb70713476fb6f7545ed1bbf32cadd7414a77d25e235aaca",
             "platform": {
                "architecture": "ppc64le",
                "os": "linux"
             }
          },
          {
             "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
             "size": 526,
             "digest": "sha256:1175fd4d728641115e2802be80abab108b8d9306442ce35425a4e8707ca60521",
             "platform": {
                "architecture": "s390x",
                "os": "linux"
             }
          }
       ]
    }
    
  • Filtra el resultado para extraer el resumen de la imagen de la plataforma que deseas. Obtén el resumen del manifiesto de la imagen de la arquitectura de CPU amd64 y el sistema operativo linux:

    curl -s https://gcr.io/v2/google-containers/pause/manifests/3.2 | \
        jq -r '.manifests[] | select(.platform.architecture=="amd64" and .platform.os=="linux") | .digest'
    

    El filtrado en este comando imita la forma en la que los entornos de ejecución del contenedor, como containerd, seleccionan la imagen que coincide con la plataforma de destino del índice de imagen.

    El resultado es similar a este:

    sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    

    El resumen de la imagen es el resultado que se obtiene después de aplicar un hash resistente a colisiones al índice de imagen o al manifiesto de imagen que, por lo general, es el algoritmoSHA-256.

  • Obtén el resumen de la imagen gcr.io/google-containers/pause-amd64:3.2:

    curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \
        | shasum -a 256 \
        | cut -d' ' -f1
    

    El resultado es similar al siguiente:

    4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    

    Puedes hacer referencia a esta imagen con el valor de resumen de la imagen de la siguiente manera:

    gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    
  • Con el concepto de almacenamiento direccionado por el contenido, obtén el manifiesto de la imagen usando el resumen como referencia:

    curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    
  • Muchos registros de imágenes de contenedor muestran el resumen de los manifiestos, los índices de imagen, los objetos de configuración y las capas del sistema de archivos en el encabezado Docker-Content-Digest como respuesta a las solicitudes HEAD HTTP. Obtén el resumen del índice de imagen de la imagen gcr.io/google-containers/pause-amd64:3.2:

    curl -s --head https://gcr.io/v2/google-containers/pause/manifests/3.2 \
        | grep -i Docker-Content-Digest \
        | cut -d' ' -f2
    

    El resultado es similar a este:

    sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
    

    Las especificaciones de la distribución de Open Container Initiative no exigen el encabezado Docker-Content-Digest, por lo que puede que este enfoque no funcione con todos los registros de imágenes de contenedor. Puedes usarlo con Artifact Registry y Container Registry.

  • Para recuperar un objeto de configuración de imagen usando el valor de resumen del manifiesto de la imagen, haz lo siguiente:

    1. Obtén el resumen de configuración:

      CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \
          | jq -r '.config.digest')
      
    2. Usa el resumen de configuración para recuperar el objeto de configuración y usa jq a fin de dar formato al resultado para facilitar su lectura:

      curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$CONFIG_DIGEST \
          | jq
      

      El resultado es similar al siguiente:

      {
        "architecture": "amd64",
        "config": {
          "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
          ],
          "Entrypoint": [
            "/pause"
          ],
          "WorkingDir": "/",
          "OnBuild": null
        },
        "created": "2020-02-14T10:51:50.60182885-08:00",
        "history": [
          {
            "created": "2020-02-14T10:51:50.60182885-08:00",
            "created_by": "ARG ARCH",
            "comment": "buildkit.dockerfile.v0",
            "empty_layer": true
          },
          {
            "created": "2020-02-14T10:51:50.60182885-08:00",
            "created_by": "ADD bin/pause-amd64 /pause # buildkit",
            "comment": "buildkit.dockerfile.v0"
          },
          {
            "created": "2020-02-14T10:51:50.60182885-08:00",
            "created_by": "ENTRYPOINT [\"/pause\"]",
            "comment": "buildkit.dockerfile.v0",
            "empty_layer": true
          }
        ],
        "os": "linux",
        "rootfs": {
          "type": "layers",
          "diff_ids": [
            "sha256:ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770"
          ]
        }
      }
      
  • Para recuperar capas del sistema de archivos con valores de resumen del manifiesto de imagen, haz lo siguiente:

    1. Obtén el resumen de la capa que deseas recuperar:

      LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \
          | jq -r '.layers[0].digest')
      
    2. Usa el resumen de capa para recuperar el archivo tar de la capa y enumera el contenido:

      curl -sL https://gcr.io/v2/google-containers/pause-amd64/blobs/$LAYER_DIGEST \
          | tar --list
      

      Esta capa solo tiene un archivo, llamado pause.

  • Para buscar etiquetas asociadas a un resumen de imagen, haz lo siguiente:

    1. Define el resumen que deseas buscar:

      IMAGE_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \
          | shasum -a 256 \
          | cut -d' ' -f1)
      

      La variable de entorno IMAGE_DIGEST contiene el resumen de la imagen a la que hace referencia la etiqueta 3.2.

    2. Usa el extremo de la lista de etiquetas de imagen, /tags/list para enumerar la información de las etiquetas y extraer las etiquetas que coincidan con el valor de resumen:

      curl -s "https://gcr.io/v2/google-containers/pause-amd64/tags/list?n=1" \
          | jq ".manifest.\"sha256:$IMAGE_DIGEST\".tag"
      

      El resultado es similar a este:

      [
        "3.2"
      ]
      
  • Para obtener el manifiesto de una imagen de un repositorio de imágenes de contenedor de Artifact Registry usando cURL, incluye un token de acceso en el encabezado de la solicitud Authorization:

    curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        https://LOCATION-docker.pkg.dev/v2/PROJECT_ID/REPOSITORY/IMAGE/manifests/DIGEST
    

    Reemplaza lo siguiente:

    • LOCATION: la ubicación regional o multirregional de tu repositorio
    • PROJECT_ID: el ID del proyecto de Google Cloud
    • REPOSITORY: el nombre de tu repositorio
    • IMAGE: el nombre de tu imagen
    • DIGEST: el resumen de tu imagen con el formato sha256:DIGEST_VALUE

¿Qué sigue?