Como usar o cache do Kaniko

Informações gerais

O Kaniko armazena em cache os artefatos de build do contêiner. Para isso, armazena e indexa camadas intermediárias em um registro de imagens de contêiner, como o próprio Artifact Registry do Google. Para saber mais sobre outros casos de uso, consulte o repositório Kaniko (em inglês) no GitHub.

O cache do Kaniko funciona da seguinte maneira:

  • O Cloud Build faz o upload de camadas de imagens de contêiner diretamente no registro, já que elas são criadas para não haver uma etapa explícita de envio. Quando todas as camadas são criadas com sucesso, um manifesto de imagem contendo essas camadas é gravado no registro.

  • O Kaniko armazena em cache todas as camadas de acordo com o conteúdo da diretiva do Dockerfile que as criou, além de todas as diretivas anteriores, até o resumo da imagem na linha FROM.

Como ativar o cache do Kaniko nas builds

É possível ativar o cache do Kaniko em uma versão do Docker substituindo os workers cloud-builders/docker por workers kaniko-project/executor em seu arquivo cloudbuild.yaml da seguinte maneira:

Compilação do Kaniko

steps:
- name: 'gcr.io/kaniko-project/executor:latest'
  args:
  - --destination=${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}
  - --cache=true
  - --cache-ttl=XXh

Compilação do Docker

steps:
- name: gcr.io/cloud-builders/docker
  args: ['build', '-t', '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}', '.']
images:
- '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'

onde:

  • --destination=${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE} é a imagem do contêiner de destino. O Cloud Build substitui automaticamente o PROJECT_ID do projeto que contém o Dockerfile. As LOCATION, REPOSITORY e IMAGE são substituis definidas pelo usuário.
  • LOCATION é o local regional ou multirregional do repositório em que a imagem está armazenada, por exemplo, us-east1.
  • REPOSITORY é o nome do repositório em que a imagem está armazenada.
  • IMAGE é o nome da imagem.
  • --cache=true ativa o cache do Kaniko;
  • O --cache-ttl=XXh define o prazo de validade do cache, em que o XX é o prazo de validade do cache em horas. Consulte Como configurar o prazo de validade do cache.

Se você executar versões usando o comando gcloud builds submit --tag [IMAGE], será possível ativar o cache do Kaniko definindo a propriedade builds/use_kaniko para True, conforme mostrado abaixo:

gcloud config set builds/use_kaniko True

Exemplo: como usar o cache do Kaniko em uma build do Node.js

Neste exemplo, você vê como executar compilações graduais de aplicativos Node.js seguindo as práticas recomendadas gerais do Dockerfile. Nesse caso, as práticas se aplicam a compilações em todas as outras linguagens compatíveis.

Neste exemplo, você transfere as diretivas que provavelmente não serão alteradas entre as compilações para a parte superior do Dockerfile e as que serão alteradas para a parte inferior. Isso torna o processo de compilação mais gradual e aumenta a velocidade dele.

Pense no seguinte Dockerfile:

FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD [ "npm", "start" ]

Esse Dockerfile faz o seguinte:

O Cloud Build precisa realizar cada etapa sempre que você executar a compilação. Isso porque não há cache de camadas de imagem entre compilações no Cloud Build. No entanto, ao executar a compilação com o cache do Kaniko ativado, o seguinte acontece:

  1. Durante a primeira execução, o Cloud Build realiza cada etapa, e cada diretiva grava uma camada no registro de imagem do contêiner.

  2. O Kaniko marca cada camada com uma chave de cache derivada do conteúdo da diretiva que produziu essa camada e todas as diretivas anteriores.

  3. Na próxima vez que o Cloud Build executar a compilação a partir do mesmo Dockerfile, ele verificará se o arquivo foi alterado. Se não tiver sido alterado, o Cloud Build usará as camadas armazenadas em cache no registro para concluir a compilação. Assim, ela é concluída mais rapidamente. Veja abaixo:

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # no change -> cached!
CMD [ "npm", "start" ]     # metadata, nothing to do

Se você modificar o arquivo package.json, o Cloud Build não precisará executar diretivas antes da etapa COPY porque o conteúdo não foi alterado. No entanto, como modificar o arquivo package.json modifica a etapa COPY, o Cloud Build precisará executar novamente todas as etapas após a etapa COPY. Veja abaixo:

FROM node:8                # no change -> cached!
COPY package*.json ./      # changed, must re-run
RUN npm install            # preceding layer changed
COPY . .                   # preceding layer changed
CMD [ "npm", "start" ]     # metadata, nothing to do

Se apenas o conteúdo do aplicativo mudar, mas suas dependências não, (o cenário mais comum), o arquivo package.json permanecerá inalterado e o Cloud Build só precisará executar novamente a etapa COPY . . final. Isso aumenta a velocidade da versão porque a etapa copia o conteúdo de origem para uma camada no registro de imagem do contêiner.

FROM node:8                # no change -> cached!
COPY package*.json ./      # no change -> cached!
RUN npm install            # no change -> cached!
COPY . .                   # changed, must re-run
CMD [ "npm", "start" ]     # metadata, nothing to do

Como configurar o prazo de validade do cache

A sinalização --cache-ttl direciona o Kaniko a ignorar camadas no cache que não foram enviadas dentro de um determinado prazo de validade.

A sintaxe é --cache-ttl=XXh em que XX é o tempo em horas. Por exemplo, o --cache-ttl=6h define o prazo de validade do cache para 6 horas. Se você executar builds usando o comando gcloud builds submit --tag [IMAGE], o valor padrão da sinalização --cache-ttl será de seis horas. Se você estiver usando a imagem do executor do Kaniko diretamente, o valor padrão será de duas semanas.

Um prazo de validade mais longo garante versões mais rápidas quando você não espera que as dependências sejam alteradas com frequência. Já um prazo mais curto garante que sua versão assimile dependências atualizadas, como pacotes Maven ou módulos Node.js, mais rapidamente, às custas do uso reduzido das camadas em cache.

Para definir o prazo de validade do cache na linha de comando, execute o seguinte comando:

gcloud config set builds/kaniko_cache_ttl XX

em que XX é o prazo de validade do cache em horas.

Em nosso exemplo do Node.js, como a saída da diretiva RUN npm install permanece inalterada, precisamos executá-la periodicamente novamente, mesmo que ela tenha sido armazenada em cache. Definir o parâmetro --cache-ttl como 6 horas é um bom compromisso porque garante que o Cloud Build execute a diretiva pelo menos uma vez por dia útil, mas não toda vez que a versão for executada.