Sobre os resumos da imagem de contêiner


Neste documento, descrevemos resumos por imagem, incluindo o que são resumos por e-mail, como encontrá-los e como aplicar o uso deles em clusters do Kubernetes. Este documento é destinado a desenvolvedores e operadores que criam e implantam imagens de contêiner.

Um resumo de imagem de contêiner (em inglês) identifica uma imagem de contêiner de maneira exclusiva e imutável. Ao implantar imagens por resumo, você evita as desvantagens da implantação por tags de imagem.

Os comandos neste documento presumem que você tenha acesso a um ambiente shell do Linux ou macOS com ferramentas como a Google Cloud CLI, Docker, cURL, jq, pack já instalado. Ou é possível usar o Cloud Shell, que tem essas ferramentas pré-instaladas.

Imagens de contêiner e tags de imagem

Ao trabalhar com imagens de contêiner, você precisa consultar as imagens usadas. As tags de imagem são uma maneira comum de se referir a diferentes revisões de uma imagem. Uma abordagem comum é marcar imagens com um identificador de versão no momento da criação. Por exemplo, v1.0.1 pode se referir a uma versão que você chama 1.0.1.

As tags facilitam a análise de imagens com strings legíveis por humanos. No entanto, as tags são referências mutáveis. Isso significa que a imagem referenciada por uma tag pode mudar, conforme ilustrado no diagrama a seguir:

Tag de imagem que aponta para uma imagem desatualizada.

Como mostrado no diagrama anterior, se você publicar uma nova imagem usando a mesma tag de uma imagem existente, a tag deixa de apontar para a imagem existente e começa a apontar para sua nova imagem.

Desvantagens das tags de imagem

Como as tags são mutáveis, elas têm as seguintes desvantagens quando você as usa para implantar uma imagem:

  • No Kubernetes, a implantação por tag pode resultar em resultados inesperados. Por exemplo, suponha que você tenha um recurso de implantação atual que referencie uma imagem de contêiner pela tag v1.0.1. Para corrigir um bug ou fazer uma pequena alteração, seu processo de criação cria uma nova imagem com a mesma tag v1.0.1. Os novos pods criados a partir do recurso de implantação podem usar a imagem antiga ou a nova, mesmo que você não altere a especificação do recurso de implantação. Esse problema também se aplica a outros recursos do Kubernetes, como StatefulSets, DaemonSets, ReplicaSets e Jobs.

  • Se você usar ferramentas para verificar ou analisar imagens, os resultados dessas ferramentas só serão válidos para a imagem que foi verificada. Para garantir a implantação da imagem que foi verificada, não é possível confiar na tag porque a imagem mencionada pela tag pode ter sido alterada.

  • Se você usa a autorização binária com o Google Kubernetes Engine (GKE), a implantação baseada em tags não é permitida porque é impossível determinar a imagem exata usada quando um pod é criado.

Quando você implanta suas imagens, é possível usar um resumo de imagem para evitar as vantagens do uso de tags. Você ainda pode adicionar tags às suas imagens, mas não precisa fazer isso.

Estrutura de uma imagem

Uma imagem consiste nos seguintes componentes:

Esses componentes são ilustrados no diagrama a seguir:

Componentes de uma imagem mostrando detalhes de um manifesto de imagem, um objeto de configuração, camadas do sistema de arquivos e um índice de imagem.

A imagem anterior mostra detalhes adicionais sobre os componentes dela:

  • O manifesto da imagem é um documento JSON que contém uma referência para o objeto de configuração, as camadas do sistema de arquivos e os metadados opcionais.
  • O manifesto de imagem referencia o objeto de configuração e cada camada do sistema de arquivos usando os atributos digest. O valor de um atributo digest é um hash criptográfico do conteúdo a que o resumo se refere, geralmente calculado usando o algoritmo SHA-256.
  • Os valores de resumo são usados para construir endereços imutáveis para os objetos. Esse processo é chamado de armazenamento endereçável de conteúdo e significa que é possível recuperar manifestos de imagens, índices de imagens, objetos de configuração e camadas com base nos resumos deles.
  • O resumo da imagem é o hash do índice da imagem ou do documento JSON do manifesto da imagem.
  • O objeto de configuração é um documento JSON que define as propriedades da imagem, como a arquitetura da CPU, o ponto de entrada, as portas expostas e as variáveis de ambiente.
  • A matriz da camada do sistema de arquivos define a ordem em que o ambiente de execução do contêiner usa para empilhar as camadas. As camadas são distribuídas como arquivos tar, normalmente compactadas com o utilitário gzip.
  • O índice de imagem opcional, às vezes chamado de lista de manifestos, refere-se a um ou mais manifestos de imagens. A referência é o resumo do manifesto da imagem. Um índice de imagens é útil quando você produz várias imagens relacionadas para plataformas diferentes, como arquiteturas amd64 e arm64.

Para mais informações, consulte a seção Como explorar manifestos, resumos e tags de imagem.

Como encontrar resumos de imagens

Para usar resumos de imagem na implantação, primeiro encontre o resumo. Em seguida, use o resumo com o comando de implantação ou inclua-o nos manifestos do Kubernetes.

É possível receber o resumo de uma imagem de várias maneiras, dependendo da situação atual. As seções a seguir contêm exemplos de diferentes produtos e ferramentas.

Nas seções a seguir, execute os comandos no Cloud Shell ou em um ambiente shell com ferramentas como a CLI gcloud, o Docker, o cURL e jq já instalados.

Artifact Registry

Container Registry

  • Para imagens armazenadas no Container Registry, use o comando gcloud container images describe para ver o resumo de uma imagem fornecendo o nome e uma tag. Use a sinalização --format para exibir apenas o resumo:

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

    O resultado será semelhante ao seguinte, embora o valor do resumo possa ser diferente:

    sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    

Cloud Build

Para imagens criadas usando o Cloud Build, é possível obter o resumo da imagem usando o comando gcloud builds describe com a sinalização --format. Essa abordagem funciona independentemente do registro usado para publicar a imagem.

  • Para uma compilação já concluída, faça o seguinte:

    1. Receba uma lista de versões para seu projeto:

      gcloud builds list
      

      Anote um BUILD_ID.

    2. Receber o resumo da imagem:

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

      Substitua BUILD_ID pelo ID exclusivo que o Cloud Build atribuiu ao build.

  • Receba o nome e o resumo da imagem para o build mais recente do Cloud Build para seu projeto atual:

    gcloud builds describe \
        $(gcloud builds list --limit 1 --format 'value(id)') \
        --format 'value[separator="@"](results.images[0].name,results.images[0].digest)'
    
  • Se seu build produziu várias imagens, filtre a saída e receba o resumo de uma das imagens:

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

    Substitua YOUR_IMAGE_NAME pelo nome de uma das imagens do arquivo cloudbuild.yaml.

  • Se você enviar um build para o Cloud Build usando o comando gcloud builds submit, será possível capturar o resumo da imagem da saída em uma variável de ambiente:

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

Cloud Native Buildpacks

  • Se você usa o Cloud Native Buildpacks e o builder do Google Cloud para criar e publicar imagens, é possível capturar o nome e o resumo da imagem usando a sinalização --quiet com o comando pack:

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

    Substitua:

    • LOCATION: o local regional ou multirregional do repositório
    • PROJECT_ID: é o ID do projeto do Google Cloud.
    • REPOSITORY: nome do repositório.
    • IMAGE: nome da sua imagem.

    O arquivo image-with-digest.txt contém o nome e o resumo da imagem.

    Use a sinalização --tag se quiser adicionar outras tags à imagem.

Cliente do Docker

  • O subcomando manifest do cliente de linha de comando docker pode buscar manifestos de imagens e listas de manifestos de registros de imagens de contêiner.

    Receba o resumo da lista de manifestos da imagem registry.k8s.io/pause:3.9 para a arquitetura de CPU amd64 e o sistema operacional 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'
    

    A saída será assim:

    sha256:8d4106c88ec0bd28001e34c975d65175d994072d65341f62a8ab0754b0fafe10
    
  • Para imagens armazenadas no daemon do Docker local e que foram extraídas ou enviadas para um registro de imagens, use a ferramenta de linha de comando do Docker para acessar o resumo da imagem:

    1. Extraia a imagem para o daemon do Docker local:

      docker pull docker.io/library/debian:bookworm
      
    2. Receber o resumo da imagem:

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

      O resultado será semelhante ao seguinte, embora o valor do resumo possa ser diferente:

      sha256:3d868b5eb908155f3784317b3dda2941df87bbbbaa4608f84881de66d9bb297b
      
  • Liste todas as imagens e resumos no seu daemon do Docker local:

    docker images --digests
    

    A saída mostra resumos para imagens que têm um valor de resumo. As imagens só terão um valor de resumo se elas forem extraídas ou enviadas para um registro de imagens.

crane e gcrane

É possível usar as ferramentas de linha de comando de código aberto crane e gcrane para receber o resumo de uma imagem sem extrair a imagem para um daemon local do Docker.

  1. Faça o download de crane e gcrane para seu diretório atual:

    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. Receber resumos por imagem:

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

    crane e gcrane têm outros recursos que estão fora do escopo deste documento. Para saber mais, consulte a documentação sobre crane e gcrane.

Como impor o uso de resumos de imagem em implantações do Kubernetes

Se você quiser aplicar usando resumos para imagens implantadas nos clusters do Kubernetes, use Controlador de políticas ou Open Policy Agent (OPA) Gatekeeper. O Policy Controller foi desenvolvido com base no projeto de código aberto do OPA Gatekeeper.

O Policy Controller e o OPA Gatekeeper se baseiam no mecanismo de políticas OPA. O Policy Controller e o OPA Gatekeeper fornecem um webhook de admissão de validação do Kubernetes para aplicar políticas e definições de recursos personalizados (CRDs) para modelos de restrição e restrições.

Os modelos de restrição contêm uma lógica de política expressa com um idioma declarativo de alto nível chamado Rego. Veja a seguir um modelo de restrição que valida que contêineres, contêineres de inicialização e contêineres efêmeros em uma especificação de recurso do Kubernetes usam imagens. com resumos:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8simagedigests
  annotations:
    metadata.gatekeeper.sh/title: "Image Digests"
    metadata.gatekeeper.sh/version: 1.0.1
    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)
          not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)
          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)
          not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)
          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)
          not regex.match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)
          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)
          }

A política anterior contém uma expressão regular como entrada para a função re_match. Essa expressão regular corresponde ao resumo da imagem do contêiner e é baseada no formato de resumo na especificação de imagem do Open Container Initiative.

As restrições aplicam a política aos recursos do Kubernetes por meio da correspondência com atributos, como kind e namespace. A restrição de exemplo a seguir aplica a política do modelo de restrição a todos os recursos Pod no namespace default.

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

Depois de criar o modelo de restrição e a restrição, todos os novos pods no namespace default precisam usar resumos por e-mail para fazer referência a imagens de contêiner.

Para ver o exemplo completo, consulte a política imagedigests na biblioteca de políticas do Gatekeeper.

Sobre manifestos, resumos e tags de imagens

Nesta seção, você aprenderá a explorar imagens existentes nos registros usando ferramentas de linha de comando, como curl e docker. Execute os comandos no Cloud Shell ou em um ambiente shell com ferramentas como a CLI gcloud, o Docker, o cURL e o jq já instalados. Os comandos a seguir usam imagens públicas no Artifact Registry.

  • Consiga o manifesto da imagem gcr.io/google-containers/pause-amd64:3.2 usando cURL e o URL do manifesto:

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

    A resposta será semelhante a:

    {
       "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"
          }
       ]
    }
    

    A seção config tem um atributo de resumo e é possível usar esse valor para recuperar o objeto de configuração. Da mesma forma, cada camada tem um atributo digest que pode ser usado para recuperar o arquivo tar dessa camada.

  • Se a imagem incluir o índice de imagem opcional, uma solicitação HTTP GET para o URL do manifesto usando uma tag retornará o índice de imagem em vez do manifesto da imagem.

    Consiga o índice da imagem gcr.io/google-containers/pause:3.2:

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

    O resultado será assim:

    {
       "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"
             }
          }
       ]
    }
    
  • Filtre o resultado para extrair o resumo de imagem da plataforma que você quer. Receba o resumo do manifesto da imagem para a arquitetura de CPU amd64 e o sistema operacional 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'
    

    A filtragem nesse comando imita como os ambientes de execução de contêiner, como containerd, selecione a imagem que corresponde à plataforma de destino do índice de imagens.

    O resultado será assim:

    sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    

    O resumo da imagem é o resultado da aplicação de umahash resistente a colisão ao índice ou ao manifesto da imagem, normalmente o SHA-256.

  • Receba o resumo da imagem 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
    

    A resposta será semelhante a:

    4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    

    É possível referenciar essa imagem usando o valor de resumo da imagem da seguinte forma:

    gcr.io/google-containers/pause-amd64@sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    
  • Com o conceito de armazenamento endereçável de conteúdo, consiga o manifesto da imagem usando o resumo como uma referência:

    curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/sha256:4a1c4b21597c1b4415bdbecb28a3296c6b5e23ca4f9feeb599860a1dac6a0108
    
  • Muitos registros de contêiner retornam o resumo de manifestos, índices de imagem, objetos de configuração e camadas do sistema de arquivos no cabeçalho Docker-Content-Digest em resposta a solicitações HTTP HEAD. Consiga o resumo do índice da imagem de 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
    

    O resultado será assim:

    sha256:927d98197ec1141a368550822d18fa1c60bdae27b78b0c004f705f548c07814f
    

    O cabeçalho Docker-Content-Digest não é exigido pelas especificações de Distribuição do Open Container Initiative. Portanto, essa abordagem pode não funcionar com todos os registros de contêiner. É possível usá-lo com o Artifact Registry e o Container Registry.

  • Para recuperar um objeto de configuração de imagem usando o valor de resumo do manifesto da imagem, faça o seguinte:

    1. Receba o resumo da configuração:

      CONFIG_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \
          | jq -r '.config.digest')
      
    2. Use o resumo de configuração para recuperar o objeto de configuração e use jq para formatar a saída para facilitar a leitura:

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

      A resposta será semelhante a:

      {
        "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 camadas do sistema de arquivos usando valores de resumo do manifesto da imagem, faça o seguinte:

    1. Receba o resumo da camada que você quer recuperar:

      LAYER_DIGEST=$(curl -s https://gcr.io/v2/google-containers/pause-amd64/manifests/3.2 \
          | jq -r '.layers[0].digest')
      
    2. Use o resumo da camada para recuperar o arquivo tar da camada e listar o conteúdo:

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

      Essa camada tem apenas um arquivo chamado pause.

  • Para pesquisar tags associadas a um resumo de imagem, faça o seguinte:

    1. Defina o resumo que você quer procurar:

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

      A variável de ambiente IMAGE_DIGEST contém o resumo da imagem referenciada pela tag 3.2.

    2. Use o endpoint de lista de tags de imagem, /tags/list, para listar informações de tag e extrair as tags para o valor de resumo:

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

      O resultado será assim:

      [
        "3.2"
      ]
      
  • Para receber o manifesto de uma imagem de um repositório de imagens de contêiner do Artifact Registry usando cURL, inclua um token de acesso no cabeçalho de solicitação Authorization:

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

    Substitua:

    • LOCATION: o local regional ou multirregional do repositório
    • PROJECT_ID: é o ID do projeto do Google Cloud.
    • REPOSITORY: nome do repositório.
    • IMAGE: nome da sua imagem.
    • DIGEST: o resumo da imagem no formato sha256:DIGEST_VALUE

A seguir