Desative o cache para comandos RUN específicos

102

Tenho alguns RUNcomandos em meu Dockerfile que gostaria de executar -no-cachesempre que construir uma imagem Docker.

Eu entendo docker build --no-cacheque desabilitará o cache de todo o Dockerfile.

É possível desabilitar o cache para um comando RUN específico?

Vingtoft
fonte
1
Depois de desativar o cache para um único comando, se o resultado não corresponder à execução anterior em cache, será necessário reconstruir todas as etapas restantes. É esse o seu objetivo ou você espera reconstruir apenas uma única camada e, de alguma forma, injetá-la onde os dados em cache anteriores estavam armazenados?
BMitch
3
Eu esperava reconstruir camadas específicas, por exemplo, um comando "git pull". No momento, o comando "git pull" será armazenado em cache, mesmo que o repo seja atualizado.
Vingtoft de
2
É fácil forçar uma atração passando um argumento não utilizado. Mas o resultado dessa entrada em cache sendo reconstruída é que todas as camadas seguintes precisarão ser reconstruídas. Veja minha resposta aqui para um exemplo.
BMitch
Se olhar para invalidar o cache quando um git remoto mudou dar uma olhada: Como evitar clone git Dockerfile cache . Todos os créditos para @anq pela resposta vinculada.
hpgmiskin,

Respostas:

82

Sempre há uma opção de inserir algum comando sem sentido e barato para executar antes da região para a qual deseja desabilitar o cache.

Conforme proposto neste comentário de problema , pode-se adicionar um bloco de argumento de construção (o nome pode ser arbitrário):

ARG CACHEBUST=1 

antes dessa região, e modifique seu valor a cada execução adicionando-o --build-arg CACHEBUST=$(date +%s)como um docker buildargumento (o valor também pode ser arbitrário, aqui é a data e hora atual, para garantir sua exclusividade nas execuções).

Isso, é claro, desabilitará o cache para todos os blocos seguintes também, já que a soma do hash da imagem intermediária será diferente, o que torna a desativação realmente seletiva do cache um problema não trivial, levando em consideração como o docker funciona atualmente.

Vladislav
fonte
1
Não parece funcionar mais, acabei de entrar ---> Using cachena linha `` ARG CACHEBUST = 1` ... (e sim, fiz --build-arg CACHEBUST=$(date +%s)no meu comando docker)
Pylinux
Também não funciona para mim, talvez dependa da plataforma. Eu esperava que qualquer alteração ARG invalidasse o cache.
Oliver,
6
Você tem que adicionar RUN echo "$CACHEBUST"porque apenas usar ARGnão invalidará o cache
Sidharth V
Esta resposta resolveu meu problema aqui: stackoverflow.com/questions/63709147/…
shapiro yaacov
28

Usar

ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache

antes da linha RUN que você deseja executar sempre. Isso funciona porque o ADD sempre buscará o arquivo / URL e o URL acima gera dados aleatórios em cada solicitação. O Docker então compara o resultado para ver se pode usar o cache.

Eu também testei isso e funciona muito bem, pois não requer nenhum argumento de linha de comando Docker adicional e também funciona a partir de um arquivo Docker-compose.yaml :)

Steve
fonte
3
o que vai acontecer se random.org decidir mudar esse endpoint? como você controlaria esse comportamento?
Andres Leon Rangel
@AndresLeonRangel Reconhecidamente, este não é um recurso do Docker, mas uma espécie de hack usando a sintaxe do Docker e um serviço da web bem conhecido que existe há mais de 20 anos. No entanto, você está certo ao dizer que eles podem descontinuar esse endpoint, na verdade, olhando seus documentos agora Não consigo nem encontrar o endpoint "randbyte" e eles têm uma nova API atualmente em beta. Você pode 1) continuar a usar este ponto de extremidade até que ele falhe, 2) usar seu novo ponto de extremidade (até que ele falhe) ou 3) escrever seu próprio ponto de extremidade aleatório, caso em que você está no controle total :)
steve
3
Isso falhou algumas vezes ... quando o site está fora do ar !!! Acho que não é a solução perfeita para isso. ADD falhou: falhou ao GET random.org/cgi-bin/randbyte?nbytes=10&format=h com status 503 Serviço indisponível: <! DOCTYPE HTML>
Kathi
1
random.org adicionou proteção DDOS que quebra essa solução agora
Brad Root
Não funciona e o endereço fornecido retorna 503. Se você não deseja bloquear seus pipelines, não use esta solução
OlegI
9

Não diretamente, mas você pode dividir seu Dockerfile em várias partes, construir uma imagem e, em seguida, FROM thisimage no início do próximo Dockerfile e construir a imagem com ou sem cache

user2915097
fonte
1
Isso permitirá a atualização das camadas confirmadas na imagem docker base?
user_mda
7

A partir de fevereiro de 2016, não é possível.

O recurso foi solicitado no GitHub

Vingtoft
fonte
5

o recurso adicionado há uma semana.

ARG FOO=bar

FROM something
RUN echo "this won't be affected if the value of FOO changes"
ARG FOO
RUN echo "this step will be executed again if the value of FOO changes"

FROM something-else
RUN echo "this won't be affected because this stage doesn't use the FOO build-arg"

https://github.com/moby/moby/issues/1996#issuecomment-550020843

Tha Sami
fonte
0

Eu acredito que esta é uma pequena melhoria na resposta de @steve, acima:

RUN git clone https://sdk.ghwl;erjnv;wekrv;[email protected]/your_name/your_repository.git

WORKDIR your_repository

# Calls for a random number to break the cahing of the git clone
# (/programming/35134713/disable-cache-for-specific-run-commands/58801213#58801213)
ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache
RUN git pull

Isso usa o cache do Docker do clone git, mas depois executa uma atualização sem cache do repositório.

Ele aparece para trabalhar, e é mais rápido - mas muitas graças a @ Steve para fornecer os princípios subjacentes.

Mike Sadler
fonte
-2

Outro truque rápido é escrever alguns bytes aleatórios antes do seu comando

RUN head -c 5 /dev/random > random_bytes && <run your command>

grava 5 bytes aleatórios que forçará uma falha de cache

Marca
fonte
10
O resultado da gravação desses bytes aleatórios também é armazenado em cache, portanto, se nenhum arquivo foi alterado antes desse comando, ele não executará o comando novamente. Isso não resolve nada.
Icy Defiance