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 compilação e arquivos intermediários, são 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 de 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, além das ferramentas usadas para criá-lo, a partir 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 de contêiner. Isso é feito ao armazenar e indexar camadas intermediárias em um registro de imagem de contêiner, como o próprio Container Registry do Google, em que ele está disponível para ser usado por criações posteriores. Para mais informações, consulte Como usar o cache do Kaniko.

Usar uma imagem do Docker em cache

A maneira mais fácil de aumentar a velocidade da criação da imagem do Docker é especificando uma imagem em cache que pode ser usada para versões subsequentes. É possível especificar a imagem em cache adicionando o argumento --cache-from ao seu arquivo de configuração da versão, que instruirá o Docker a criar usando essa imagem como uma origem de 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 criação. Deste modo, usar --cache-from não é vantajoso se você alterar uma camada nos estágios iniciais da sua versão do Docker.

É recomendável que você sempre use --cache-from para suas criações, mas tenha em mente as seguintes condições:

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

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. Observe que a etapa de criação do docker pull abaixo define o entrypoint para bash, o que torna possível 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 para 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. Observe que a etapa da criação do docker pull abaixo define o entrypoint para bash, o que torna possível 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 para 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 versão, reutilize os resultados de uma versão anterior. Você pode copiar os resultados de uma versão anterior para um bucket do Google Cloud Storage, usar os resultados para um cálculo mais rápido e, em seguida, copiar os novos resultados de volta ao bucket. Use esse método quando sua criação tomar muito tempo e produzir um pequeno número de arquivos que não demoram para ser copiados do Google Cloud Storage e para ele.

Ao contrário de --cache-from, que é somente para criações do Docker, o armazenamento em cache do Google Cloud Storage pode ser usado para qualquer criador 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 versão, adicione instruções para os seguintes objetivos:

    • Copiar os resultados de uma versão anterior do bucket do Google Cloud Storage.
    • Usar os resultados para a versão atual.
    • Copiar os novos resultados de volta para o bucket.

      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 versão, adicione instruções para os seguintes objetivos:

    • Copiar os resultados de uma versão anterior do bucket do Google Cloud Storage.
    • Usar os resultados para a versão atual.
    • Copiar os novos resultados de volta para o bucket.

      {
          "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 versões. Para aumentar a velocidade da sua versão, 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 sua criação porque o Cloud Build só 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 .
    

Evitar o upload de arquivos desnecessários

Quando uma versão é acionada, é feito upload do diretório do seu código para uso pelo Cloud Build.

É possível excluir arquivos não necessários para sua versão com um arquivo .gcloudignore para otimizar o tempo de upload.

Exemplos de arquivos comumente excluídos incluem:

  • 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 para 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 de dependências de terceiros também resulta em um processo de criação mais consistente e em um risco reduzido de implantação acidental de código que ainda está em desenvolvimento ativo.