Práticas recomendadas para acelerar builds

Nesta página, apresentamos as práticas recomendadas para acelerar as builds do Cloud Build.

Como criar contêineres mais enxutos

Quando você coloca um aplicativo em contêineres, os arquivos que não são necessários no ambiente de execução, como dependências de tempo de build e arquivos intermediários, podem ser incluídos inadvertidamente na imagem do contêiner. Esses arquivos desnecessários aumentam o tamanho da imagem e geram mais tempo e custo à medida que ela é transferida entre o registro da imagem do contêiner e o ambiente de execução do contêiner.

Para reduzir o tamanho da imagem do contêiner, separe a criação do aplicativo e as ferramentas usadas para criá-lo da montagem do contêiner do ambiente de execução.

Para mais informações, consulte Como criar contêineres mais enxutos.

Como usar o cache do Kaniko

O cache do Kaniko é um recurso do Cloud Build que armazena em cache os artefatos de criação do contêiner. Isso é feito ao armazenar e indexar camadas intermediárias em um registro da imagem do contêiner, como o próprio Container Registry do Google, em que eles estão disponíveis para uso em builds posteriores. Para mais informações, consulte Como usar o cache do Kaniko.

Como usar uma imagem do Docker em cache

A maneira mais fácil de aumentar a velocidade da build da imagem do Docker é especificando uma imagem em cache que possa ser usada em builds posteriores. É possível especificar a imagem em cache adicionando o argumento --cache-from ao arquivo de configuração de build, que instruirá o Docker a criar usando essa imagem como uma origem do cache.

Cada imagem do Docker é composta de camadas empilhadas. O uso de --cache-from recria todas as camadas, desde a camada alterada até o final da build. Deste modo, o uso de --cache-from não será vantajoso se você alterar uma camada nos estágios iniciais da build do Docker.

É recomendável sempre usar --cache-from nas builds, mas considerando as seguintes condições:

  • Você precisa de uma imagem do Docker criada anteriormente para armazenar em cache.
  • É possível usar --cache-from apenas para builds do Docker. Não o use para builders que criam outros tipos de artefatos.
  • É preciso recuperar a imagem em cache de um registro, o que pode aumentar o tempo necessário para a build.

Nas etapas a seguir, explicamos como criar usando uma imagem previamente armazenada em cache:

YAML

  1. Na configuração da sua versão, adicione instruções para os seguintes objetivos:

    • Envie a imagem em cache do Container Registry. A etapa de criação docker pull abaixo define entrypoint como bash, o que permite executar o comando e ignorar o erro retornado. Isso é obrigatório quando você cria uma imagem pela primeira vez, e o docker pull não tem uma imagem atual a ser extraída.
    • Adicione um argumento --cache-from para usar essa imagem nas recriações.

      steps:
           - name: 'gcr.io/cloud-builders/docker'
             entrypoint: 'bash'
             args:
             - '-c'
             - |
               docker pull gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest || exit 0
          - name: 'gcr.io/cloud-builders/docker'
            args: [
                      'build',
                      '-t', 'gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest',
                      '--cache-from', 'gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest',
                      '.'
                  ]
          images: ['gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest']
          

      em que [IMAGE_NAME] é o nome da sua imagem.

  2. Crie sua imagem usando a configuração de versão acima:

    gcloud builds submit --config cloudbuild.yaml .
        

JSON

  1. Na configuração da sua versão, adicione instruções para os seguintes objetivos:

    • Envie a imagem em cache do Container Registry. A etapa da criação docker pull abaixo define entrypoint como bash, o que permite executar o comando e ignorar os erros retornados. Isso é obrigatório quando você cria uma imagem pela primeira vez, e o docker pull não tem uma imagem atual a ser extraída.
    • Adicione um argumento --cache-from para usar essa imagem nas recriações.

      {
              "steps": [
              {
                  "name": "gcr.io/cloud-builders/docker",
                  "entrypoint": "bash",
                  "args": ["-c", "docker pull gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest || exit 0"]
              },
              {
                  "name": "gcr.io/cloud-builders/docker",
                  "args": [
                      "build",
                      "-t",
                      "gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest",
                      "--cache-from",
                      "gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest",
                      "."
                  ]
              }
              ],
              "images": ["gcr.io/$PROJECT_ID/[IMAGE_NAME]:latest"]
          }
          

      em que [IMAGE_NAME] é o nome da sua imagem.

  2. Crie sua imagem usando a configuração de versão acima:

    gcloud builds submit --config cloudbuild.json .
        

Como armazenar diretórios em cache com o Google Cloud Storage

Para aumentar a velocidade de uma build, reutilize os resultados de uma build anterior. Copie os resultados da build anterior para um bucket do Google Cloud Storage, use os resultados para um cálculo mais rápido e copie os novos resultados de volta ao bucket. Use esse método quando a build levar muito tempo e produzir um pequeno número de arquivos que não demoram para ser copiados de e para o Google Cloud Storage.

Ao contrário de --cache-from, que é somente para builds do Docker, o armazenamento em cache do Google Cloud Storage pode ser usado com qualquer builder compatível com o Cloud Build.

Use as etapas a seguir para armazenar diretórios em cache usando o Google Cloud Storage:

YAML

  1. No arquivo de configuração de build, adicione instruções para as seguintes ações:

    • Copiar os resultados de uma build anterior do bucket do Google Cloud Storage.
    • Usar os resultados na build atual.
    • Copiar os novos resultados de volta para o intervalo.

      steps:
          - name: gcr.io/cloud-builders/gsutil
            args: ['cp', 'gs://mybucket/results.zip', 'previous_results.zip']
          # operations that use previous_results.zip and produce new_results.zip
          - name: gcr.io/cloud-builders/gsutil
            args: ['cp', 'new_results.zip', 'gs://mybucket/results.zip']
          
  2. Crie seu código usando a configuração de versão acima:

    gcloud builds submit --config cloudbuild.yaml .
        

JSON

  1. No arquivo de configuração de build, adicione instruções para as seguintes ações:

    • Copiar os resultados de uma build anterior do bucket do Google Cloud Storage.
    • Usar os resultados na build atual.
    • Copiar os novos resultados de volta para o intervalo.

      {
              "steps": [
              {
                  "name": "gcr.io/cloud-builders/gsutil",
                  "args": ["cp", "gs://mybucket/results.zip", "previous_results.zip"]
              },
              {
                  // operations that use previous_results.zip and produce new_results.zip
              },
              {
                  "name": "gcr.io/cloud-builders/gsutil",
                  "args": ["cp", "new_results.zip", "gs://mybucket/results.zip"]
              }
              ]
          }
          
  2. Crie seu código usando a configuração de versão acima:

    gcloud builds submit --config cloudbuild.json .
        

Como usar tamanhos personalizados de máquinas virtuais

Além do tipo de máquina padrão, o Cloud Build oferece dois tipos de máquinas virtuais de alta CPU para executar as builds. Para aumentar a velocidade da build, selecione uma máquina virtual com uma CPU mais alta. Solicitar uma máquina com CPU alta pode aumentar o tempo de inicialização da build porque o Cloud Build apenas inicia essas máquinas sob demanda.

Para mais informações sobre como selecionar tamanhos de disco personalizados, consulte diskSize.

Nas etapas a seguir, explicamos como especificar um tamanho de VM personalizado para uma build:

gcloud

Para especificar um tamanho de VM personalizado, use o argumento --machine-type:

gcloud builds submit --config=cloudbuild.yaml \
        --machine-type=n1-highcpu-8 .
    

YAML

  1. Especifique o tamanho da VM no seu arquivo de configuração de versão:

    steps:
        - name: 'gcr.io/cloud-builders/docker'
          args: ['build', '-t', 'gcr.io/my-project/image1', '.']
          # operations that take a long time to build
        - name: 'gcr.io/cloud-builders/docker'
          args: ['build', '-t', 'gcr.io/my-project/image2', '.']
        options:
          machineType: 'N1_HIGHCPU_8'
        
  2. Crie usando a configuração de versão acima:

    gcloud builds submit --config cloudbuild.yaml .
        

JSON

  1. Especifique o tamanho da VM no seu arquivo de configuração de versão:

    {
            "steps": [
            {
                "name": "gcr.io/cloud-builders/docker",
                "args": ["build", "-t", "gcr.io/my-project/image1", "."]
            },
            // operations that take a long time to build
            {
                "name": "gcr.io/cloud-builders/docker",
                "args": ["build", "-t", "gcr.io/my-project/image2", "."]
            }
            ],
            "options": {
                "machineType": "N1_HIGHCPU_8"
            }
        }
        
  2. Crie usando a configuração de versão acima:

    gcloud builds submit --config cloudbuild.json .
        

Como evitar o upload de arquivos desnecessários

Quando uma build é acionada, o upload do diretório do código é feito para uso do Cloud Build.

É possível excluir arquivos desnecessários à build com um arquivo .gcloudignore para otimizar o tempo de upload.

Veja a seguir exemplos dos arquivos que costumam ser excluídos:

  • Documentação e código de amostra de desenvolvedores de projetos
  • Código de scaffolding gerado, binários, arquivos *.jar ou recursos da Web compilados usados para desenvolvimento
  • Dependências de pacotes de terceiros para desenvolvimento local

Para preparar um arquivo .gcloudignore a fim de atender a esses casos, crie um arquivo na raiz do projeto com conteúdo como:

.git
    dist
    node_modules
    vendor
    *.jar
    

A exclusão do código compilado e das dependências de terceiros também resulta em um processo de build mais consistente e em um risco reduzido de implantação acidental do código que ainda está em desenvolvimento ativo.