Criar imagens de contêiner

Nesta página, descrevemos como configurar o Cloud Build para criar e armazenar imagens do Docker. Se você ainda não conhece o Cloud Build, leia os guias de início rápido e a visão geral da configuração do build primeiro.

O Cloud Build fornece imagens pré-criadas que podem ser consultadas em um arquivo de configuração do Cloud Build para executar suas tarefas. Essas imagens são compatíveis e mantidas pelo Google Cloud. Use a imagem compatível e pré-criada do Docker para executar comandos e criar imagens Docker.

Antes de começar

As instruções nesta página presumem que você tenha familiaridade com o Docker. Além disso:

  • Tenha o código-fonte do aplicativo e o Dockerfile.
  • Tenha um repositório do Docker para armazenar imagens no Artifact Registry ou crie um novo repositório.
  • Para usar os comandos gcloud desta página, instale a Google Cloud CLI.
  • Se você quiser executar as imagens, instale o Docker.
  • Se você quiser assinar as imagens com cosign, siga as instruções em Autorizar o acesso serviço a serviço para criar uma conta de serviço especificada pelo usuário e conceder as permissões necessárias para gerar tokens de ID.

Criar com um arquivo de configuração de build

Para criar sua imagem do Docker usando um arquivo de configuração de build:

  1. no mesmo diretório que contém o código-fonte do aplicativo, crie um arquivo chamado cloudbuild.yaml ou cloudbuild.json;
  2. No arquivo de configuração de build:

    • Adicione um campo name e especifique a imagem do Docker pré-criada. A imagem pré-criada é armazenada em gcr.io/cloud-builders/docker. No arquivo de configuração de exemplo abaixo, o campo name especifica que a imagem do Docker pré-criada é usada pelo Cloud Build para executar a tarefa indicada pelo campo args.
    • No campo args, adicione os argumentos para criar a imagem.

      YAML

      steps:
      - name: 'gcr.io/cloud-builders/docker'
        args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.' ]
      

      JSON

      {
       "steps": [
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
              "build",
              "-t",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
              "."
             ]
         }
         ]
       }
      

      Substitua os valores de marcador na configuração da versão acima pelo seguinte:

    • LOCATION: o local regional ou multirregional do seu repositório do Docker no Artifact Registry.

    • PROJECT_ID: é seu ID do projeto no Google Cloud.

    • REPOSITORY: o nome do repositório do Docker no Artifact Registry.

    • IMAGE_NAME: o nome da imagem do contêiner.

      Se Dockerfile e o código-fonte estiverem em diretórios diferentes, adicione -f e o caminho para Dockerfile à lista de argumentos no campo args:

      YAML

      steps:
      - name: 'gcr.io/cloud-builders/docker'
        args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '-f', 'DOCKERFILE_PATH', '.' ]
      

      JSON

      {
       "steps": [
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
              "build",
              "-t",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME", '-f', 'DOCKERFILE_PATH', "."
             ]
         }
         ]
       }
      

      Substitua os valores de marcador na configuração da versão acima pelo seguinte:

      • LOCATION: o local regional ou multirregional do seu repositório.
      • PROJECT_ID: é seu ID do projeto no Google Cloud.
      • REPOSITORY: o nome do repositório do Artifact Registry.
      • IMAGE_NAME: o nome da imagem do contêiner.
      • DOCKERFILE_PATH: caminho para Dockerfile.
  3. Inicie a compilação usando o arquivo de configuração da compilação:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    Substitua os valores de marcador no comando acima pelo seguinte:

    • CONFIG_FILE_PATH: o caminho para o arquivo de configuração do build.
    • SOURCE_DIRECTORY: o caminho ou URL do código-fonte.

    Se você não especificar CONFIG_FILE_PATH e SOURCE_DIRECTORY no comando gcloud builds submit, o Cloud Build presumirá que o arquivo de configuração e o código-fonte estão no diretório de trabalho atual.

Criar com um Dockerfile

O Cloud Build permite que você crie uma imagem do Docker usando apenas um Dockerfile. Você não precisa de um arquivo de configuração de build à parte.

Para criar usando um Dockerfile, execute o seguinte comando no diretório que contém seu código-fonte e o Dockerfile:

    gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME

Substitua os valores de marcador no comando acima pelo seguinte:

  • LOCATION: o local regional ou multirregional do seu repositório.
  • PROJECT_ID: é seu ID do projeto no Google Cloud.
  • REPOSITORY: o nome do repositório do Artifact Registry.
  • IMAGE_NAME: o nome da imagem do contêiner.

Crie com os buildpacks do Google Cloud

O Cloud Build permite que você crie uma imagem sem um Dockerfile ou um arquivo de configuração da versão. É possível fazer isso usando os buildpacks do Google Cloud.

Para criar usando pacotes de criação, execute o seguinte comando no diretório que contém seu código-fonte:

    gcloud builds submit --pack builder=BUILDPACK_BUILDER, \
        env=ENVIRONMENT_VARIABLE, \
        image=IMAGE_NAME

Substitua os valores dos marcadores nos comandos acima pelo seguinte:

  • BUILDPACK_BUILDER: o builder do pacote de criação a ser usado. Se você não especificar um builder, o Cloud Build usará gcr.io/buildpacks/builder por padrão.
  • ENVIRONMENT_VARIABLE: qualquer variável de ambiente para a versão.
  • IMAGE: o URL da imagem no Artifact Registry. O URL da imagem precisa estar no formato LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME.

Veja alguns comandos de exemplo:

  • Como executar uma versão usando o gcr.io/buildpacks/builder padrão para criar a imagem us-docker.pkg.dev/gcb-docs-project/containers/gke/hello-app:

      gcloud builds submit --pack image=us-docker.pkg.dev/gcb-docs-project/containers/gke/hello-app
    
  • Como transmitir várias variáveis de ambiente para sua versão usando ^--^ como um separador. Para mais informações sobre como usar argumentos de escape, consulte gcloud topic escaping.

      gcloud builds submit --pack \
          ^--^image=gcr.io/my-project/myimage--env=GOOGLE_ENTRYPOINT='java -jar target/myjar.jar',GOOGLE_RUNTIME_VERSION='3.1.301'
    

Configuração de gatilhos para usar o buildpacks: além de criar usando a linha de comando, é possível configurar os gatilhos para usar buildpacks para criar a imagem automaticamente. Para saber mais, consulte Como criar e gerenciar gatilhos de compilação.

Diferentes formas de armazenar imagens no Artifact Registry

Configure o Cloud Build para armazenar sua imagem criada de uma das seguintes maneiras:

  • usando o campo images, que armazena a imagem no Artifact Registry após a conclusão do build.
  • usando o comando docker push, que armazena a imagem no Artifact Registry como parte do fluxo de build.

A diferença entre o uso do campo images e do comando push do Docker é que, se você usar o campo images, a imagem armazenada será exibida nos resultados da versão. Isso inclui a página Descrição do build para um build no console do Google Cloud, os resultados de Build.get() e os resultados de gcloud builds list. No entanto, se você usar o comando push do Docker para armazenar a imagem criada, ela não será exibida nos resultados da versão.

Se quiser armazenar a imagem como parte de seu fluxo de build e exibir a imagem nos resultados do build, use o comando push do Docker e o campo images em seu arquivo de configuração de build.

Para armazenar uma imagem de contêiner no Artifact Registry após a conclusão do build:

  1. Se o repositório de destino não existir, crie um novo repositório.
  2. no mesmo diretório que contém o código-fonte do aplicativo e Dockerfile, crie um arquivo chamado cloudbuild.yaml ou cloudbuild.json;
  3. no seu arquivo de configuração de build, adicione uma etapa da criação para criar uma imagem e, em seguida, adicione um campo images especificando a imagem criada. Isso armazena a imagem no Artifact Registry. O snippet abaixo mostra uma configuração de build para criar uma imagem e armazená-la no Artifact Registry:

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.' ]
    images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    

    JSON

    {
    "steps": [
    {
        "name": "gcr.io/cloud-builders/docker",
        "args": [
            "build",
            "-t",
            "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
            "."
        ]
    }
    ],
    "images": [
        "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
    ]
    }
    

    Em que:

    • LOCATION: o local regional ou multirregional do seu repositório.
    • PROJECT_ID: é seu ID do projeto no Google Cloud.
    • REPOSITORY: o nome do repositório do Artifact Registry.
    • IMAGE_NAME: o nome da imagem do contêiner.
  4. Inicie o build usando o arquivo de configuração do build:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    Em que:

    • CONFIG_FILE_PATH é o caminho para o arquivo de configuração da compilação;
    • SOURCE_DIRECTORY é o caminho ou o URL do código-fonte.

Para armazenar a imagem no Artifact Registry como parte do fluxo de build:

  1. no mesmo diretório que contém o código-fonte do aplicativo e Dockerfile, crie um arquivo chamado cloudbuild.yaml ou cloudbuild.json;

  2. no seu arquivo de configuração de build, adicione uma etapa de build docker para criar uma imagem, adicione outra etapa de build docker e transmita argumentos para invocar o comando push:

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.']
    - name: 'gcr.io/cloud-builders/docker'
      args: ['push', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    

    JSON

    {
      "steps": [
       {
          "name": "gcr.io/cloud-builders/docker",
          "args": [
              "build",
              "-t",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
              "."
           ]
       },
       {
           "name": "gcr.io/cloud-builders/docker",
           "args": [
              "push",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
            ]
       }
      ]
    }
    

    Em que:

    • LOCATION: o local regional ou multirregional do seu repositório.
    • PROJECT_ID: é seu ID do projeto no Google Cloud.
    • REPOSITORY: o nome do repositório do Artifact Registry.
    • IMAGE_NAME: o nome da imagem do contêiner.
  3. Inicie o build usando o arquivo de configuração do build:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    Em que:

    • CONFIG_FILE_PATH é o caminho para o arquivo de configuração da compilação;
    • SOURCE_DIRECTORY é o caminho ou o URL do código-fonte.

Para armazenar uma imagem como parte de seu fluxo de build e para exibir a imagem nos resultados do build:

  1. no mesmo diretório que contém o código-fonte do aplicativo e Dockerfile, crie um arquivo chamado cloudbuild.yaml ou cloudbuild.json;
  2. no arquivo de configuração de build, após a etapa de criação da imagem, adicione uma etapa para invocar o comando push do Docker e, em seguida, adicione o campo images:

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.']
    - name: 'gcr.io/cloud-builders/docker'
      args: ['push', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    

    JSON

    {
        "steps": [
       {
           "name": "gcr.io/cloud-builders/docker",
           "args": [
               "build",
               "-t",
               "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
               "."
            ]
       },
       {
           "name": "gcr.io/cloud-builders/docker",
           "args": [
               "push",
               "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
            ]
       }
       ],
        "images": [
           "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
        ]
    }
    

    Em que:

    • LOCATION: o local regional ou multirregional do seu repositório.
    • PROJECT_ID: é seu ID do projeto no Google Cloud.
    • REPOSITORY: o nome do repositório do Artifact Registry.
    • IMAGE_NAME: o nome da imagem do contêiner.
  3. Inicie o build usando o arquivo de configuração do build:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    Em que:

    • CONFIG_FILE_PATH é o caminho para o arquivo de configuração da compilação;
    • SOURCE_DIRECTORY é o caminho ou o URL do código-fonte.

Assinar imagens de contêiner com cosign

Se você estiver armazenando imagens no Artifact Registry, adicione outra camada de segurança usando a ferramenta cosign para criar um registro de qual conta de serviço é usada para iniciar um build. Com o padrão OpenID Connect (OIDC), os auditores podem usar esse registro para verificar se uma imagem foi criada por uma conta de serviço confiável.

As etapas a seguir demonstram como usar o arquivo de configuração cloudbuild.yaml para receber um token de identidade e assinar sua imagem de contêiner.

YAML

  steps:
  - name: 'gcr.io/cloud-builders/docker'
    id: 'tag-and-push'
    script: |
      #!/bin/sh
      set -e
      docker build -t $_IMAGE .
      docker push "$_IMAGE"
      docker inspect $_IMAGE --format "$_IMAGE@{{.Id}}" >image_with_digest
  - name: 'gcr.io/cloud-builders/gcloud'
    id: 'generate-token'
    script: |
      #!/bin/sh
      set -e
      gcloud auth print-identity-token --audiences=sigstore > token
  - name: 'gcr.io/cloud-builders/docker'
    id: 'sign-image'
    script: |
      #!/bin/sh
      set -e
      docker run \
      --network=cloudbuild \
      --mount source=home-volume,target=/builder/home \
      --rm \
      -e SIGSTORE_NO_CACHE=true \
      -e HOME=/builder/home \
      gcr.io/projectsigstore/cosign \
      sign --identity-token=$(cat token) $(cat image_with_digest) -y
  service_account: '$_SERVICE_ACCOUNT'
  artifacts:
    images:
    - $_IMAGE
  substitutions:
    _IMAGE: 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME'
    _SERVICE_ACCOUNT_ID: 'SERVICE_ACCOUNT_ID'
    _SERVICE_ACCOUNT: projects/${PROJECT_ID}/serviceAccounts/${_SERVICE_ACCOUNT_ID}
  options:
    env:
    - '_IMAGE=$_IMAGE'
    dynamic_substitutions: true
    logging: CLOUD_LOGGING_ONLY

JSON

    {
        "steps": [
            {
                "name": "gcr.io/cloud-builders/docker",
                "id": "tag-and-push",
                "script": "#!/bin/sh set -e \ndocker build -t $_IMAGE . \ndocker push \"$_IMAGE\""
            },
            {
                "name": "gcr.io/cloud-builders/gcloud",
                "id": "generate-token-and-get-digest",
                "script": "#!/bin/sh set -e \ngcloud auth print-identity-token --audiences=sigstore > token \ngcloud container images describe \"$_IMAGE\" --format=\"value(image_summary.fully_qualified_digest)\" > image_with_digest"
            },
            {
                "name": "gcr.io/projectsigstore/cosign",
                "id": "sign-image",
                "script": "#!/busybox/sh cosign sign --identity-token=$(cat token) $(cat image_with_digest) -y",
                "env": [
                    "SIGSTORE_NO_CACHE=true"
                ]
            }
        ],
        "service_account": "$_SERVICE_ACCOUNT",
        "artifacts": {
            "images": [
                "$_IMAGE"
            ]
        },
        "substitutions": {
            "_IMAGE": "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
            "_SERVICE_ACCOUNT_ID": "SERVICE_ACCOUNT_ID",
            "_SERVICE_ACCOUNT": "projects/${PROJECT_ID}/serviceAccounts/${_SERVICE_ACCOUNT_ID}"
        },
        "options": {
            "env": [
                "_IMAGE=$_IMAGE"
            ],
            "dynamic_substitutions": true,
            "logging": "CLOUD_LOGGING_ONLY"
        }
    }

Em que:

  • LOCATION é o local regional ou multirregional do repositório em que a imagem está armazenada, por exemplo, us-east1 ou us.

  • PROJECT_ID: é seu ID do projeto no Google Cloud.

  • REPOSITORY é o nome do repositório em que a imagem é armazenada.

  • IMAGE_NAME é o nome da imagem.

  • SERVICE_ACCOUNT_ID é o endereço de e-mail da conta de serviço especificada pelo usuário em que você quer executar o build. Por exemplo, o endereço de e-mail de uma conta de serviço tem esta aparência: service-account-name@project-id.iam.gserviceaccount.com.

Para verificar a assinatura, instale o cosign na máquina local e execute o comando cosign verify:

cosign verify \
--certificate-identity=SERVICE_ACCOUNT_ID \
--certificate-oidc-issuer=https://accounts.google.com \
IMAGE

Em que:

  • SERVICE_ACCOUNT_ID é o endereço de e-mail da conta de serviço confiável que você espera ter sido usada para criar a imagem do contêiner.
  • IMAGE é o nome completo da imagem, incluindo o resumo de imagem sha256.

Executar a imagem do Docker

Para verificar se a imagem que você criou funciona como esperado, é possível executá-la usando o Docker.

  1. Configure o Docker para usar suas credenciais do Artifact Registry ao interagir com ele. Você só precisa fazer isso uma vez. Use o comando a seguir para fazer a autenticação usando o auxiliar de credencial do gcloud.

    gcloud auth configure-docker HOSTNAME-LIST
    

    Em que HOSTNAME-LIST é uma lista separada por vírgulas de nomes de host do repositório a serem adicionados à configuração auxiliar de credenciais.

    Por exemplo, para adicionar as regiões us-central1 e asia-northeast1, execute o comando:

    gcloud auth configure-docker us-central1-docker.pkg.dev,asia-northeast1-docker.pkg.dev
    
  2. Execute a imagem Docker que você criou anteriormente:

    docker run LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME
    

    Em que:

    • LOCATION: o local regional ou multirregional do seu repositório.
    • PROJECT_ID: é seu ID do projeto no Google Cloud.
    • REPOSITORY: o nome do repositório do Artifact Registry.
    • IMAGE_NAME: o nome da imagem do contêiner.

    Você verá um resultado semelhante a este:

    Hello, world! The time is Fri Feb  2 16:09:54 UTC 2018.
    

A seguir