Skip to content
Latchkey

Cache de camadas do Docker explicado: builds de imagem mais rápidos no CI

O Docker constrói uma imagem como uma pilha de camadas com cache. Ordene seu Dockerfile para que as partes que raramente mudam venham primeiro, e a maioria dos builds reutiliza quase tudo.

Cada instrução em um Dockerfile produz uma camada. O Docker pode reutilizar uma camada de um build anterior se suas entradas não mudaram - mas uma única alteração no início invalida tudo depois dela. A ordenação é tudo.

Como as camadas são cacheadas

O Docker faz hash de cada instrução e suas entradas. Se o hash corresponder a uma camada em cache, ele a reutiliza em vez de reexecutar o step. No momento em que as entradas de uma camada mudam, essa camada e todas as abaixo são reconstruídas - o cache é invalidado para baixo, não seletivamente.

Ordenar para acertar o cache

Coloque as instruções estáveis primeiro e as voláteis por último. Copie seu manifesto de dependências e instale as dependências *antes* de copiar o source da aplicação, para que uma alteração de código não estrague a camada de instalação de dependências.

Cache-friendly ordering
COPY package*.json ./
RUN npm ci          # cached unless deps change
COPY . .            # changes often; only this layer rebuilds
RUN npm run build

Por que o CI costuma errar o cache

  • Runners efêmeros começam sem cache local de imagem a cada execução.
  • Nenhum backend de cache externo configurado, então nada é restaurado.
  • Copiar o source antes de instalar as deps, invalidando as deps a cada commit.
  • Um build argument variável perto do topo do arquivo estragando tudo.

Cache entre execuções de CI

Como runners efêmeros não têm cache local, você precisa de um externo: o cache baseado em registry do BuildKit (--cache-from / --cache-to) armazena camadas em um registry para que a próxima execução as restaure. Sem isso, todo build de CI é efetivamente um build a frio.

Principais conclusões

  • Cada instrução do Dockerfile é uma camada; uma alteração invalida todas as abaixo.
  • Ordene os steps estáveis primeiro, os voláteis (copy do source) por último.
  • Instale dependências antes de copiar o source da app para acertos confiáveis.
  • CI efêmero precisa de um cache externo (baseado em registry) para acertar o cache.

Guias relacionados