Como forçar o Docker a criar uma imagem limpa de uma imagem

818

Criei uma imagem do Docker a partir de um arquivo do Docker usando o comando abaixo.

$ docker build -t u12_core -f u12_core .

Quando estou tentando reconstruí-lo com o mesmo comando, ele está usando o cache de compilação como:

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <[email protected]>
 ---> Using cache
 ---> 4354ccf9dcd8
Step 3 : RUN apt-get update
 ---> Using cache
 ---> bcbca2fcf204
Step 4 : RUN apt-get install -y openjdk-7-jdk
 ---> Using cache
 ---> 103f1a261d44
Step 5 : RUN apt-get install -y openssh-server
 ---> Using cache
 ---> dde41f8d0904
Step 6 : RUN apt-get install -y git-core
 ---> Using cache
 ---> 9be002f08b6a
Step 7 : RUN apt-get install -y build-essential
 ---> Using cache
 ---> a752fd73a698
Step 8 : RUN apt-get install -y logrotate
 ---> Using cache
 ---> 93bca09b509d
Step 9 : RUN apt-get install -y lsb-release
 ---> Using cache
 ---> fd4d10cf18bc
Step 10 : RUN mkdir /var/run/sshd
 ---> Using cache
 ---> 63b4ecc39ff0
Step 11 : RUN echo 'root:root' | chpasswd
 ---> Using cache
 ---> 9532e31518a6
Step 12 : RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
 ---> Using cache
 ---> 47d1660bd544
Step 13 : RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
 ---> Using cache
 ---> d1f97f1c52f7
Step 14 : RUN wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12'
 ---> Using cache
 ---> bd7dde7a98b9
Step 15 : RUN tar -xvf aerospike.tgz
 ---> Using cache
 ---> 54adaa09921f
Step 16 : RUN dpkg -i aerospike-server-community-*/*.deb
 ---> Using cache
 ---> 11aba013eea5
Step 17 : EXPOSE 22 3000 3001 3002 3003
 ---> Using cache
 ---> e33aaa78a931
Step 18 : CMD /usr/sbin/sshd -D
 ---> Using cache
 ---> 25f5fe70fa84
Successfully built 25f5fe70fa84

O cache mostra que o aerospike está instalado. No entanto, não o encontro dentro de contêineres que aparecem nessa imagem, então quero reconstruí-la sem usar o cache. Como forçar o Docker a reconstruir uma imagem limpa sem o cache?

Pavan Gupta
fonte
10
Como um aparte, você geralmente deve tentar minimizar o número de RUNdiretivas.
tripleee
4
@tripleee Você pode explicar o porquê?
Ya.
9
@Ya. Antes, o Docker sempre criava uma camada separada para cada RUNdiretiva; portanto, uma Dockerfilecom muitas RUNdiretivas consumia quantidades gigantescas de espaço em disco; mas isso aparentemente melhorou um pouco nas versões recentes.
Tripleee
Quando tento docker-compose up -d, onde posso usar --no-cache?
Oo
@Oo isso não é possível. Você primeiro tem que fazer docker-compose build --no-cachee depoisdocker-compose up -d
Martin Melka

Respostas:

1445

Existe uma --no-cacheopção:

docker build --no-cache -t u12_core -f u12_core .

Nas versões mais antigas do Docker, você precisava passar --no-cache=true, mas esse não é mais o caso.

Assaf Lavie
fonte
89
Observe também que --no-cachefunciona com docker-compose build.
Blackus
42
Você também pode querer usar --pull. Isso solicitará ao docker para obter a versão mais recente da imagem base. Isso é necessário, além de --no-cachese você já possui a imagem de base (ex:) ubuntu/lateste a imagem de base foi atualizada desde a última vez que você a extraiu. Veja os documentos aqui .
Collin Krawll
2
@CollinKrawll: A --pullopção fez o truque para mim. Apenas --no-cache, a construção ainda está quebrada. Coloque --pulltambém, a construção funcionou! Obrigado!
Erdős-Bacon
1
Se alguém estiver chamando a construção do docker, não será assumido que ele deseja reconstruir sem o cache? Em que caso de uso alguém iria querer criar uma imagem e usar uma imagem criada anteriormente? <rant> Acabei de perder um dia porque uma construção anterior falhou silenciosamente, mas foi concluída com êxito "e estava usando a imagem quebrada, sem entender por que as atualizações no script de construção não estavam funcionando </rant>
Jeff
3
@ Jeff Quando você está desenvolvendo uma imagem do docker, a construção do docker refaz apenas as camadas / etapas que foram modificadas. Se eu tiver cinco etapas e adicionar uma nova etapa no índice 3, as camadas associadas às etapas 1 e 2 poderão ser reutilizadas. Isso acelera enormemente o processo de desenvolvimento
flakes
130

Em alguns casos extremos, sua única maneira de contornar falhas de compilação recorrentes é executando:

docker system prune

O comando solicitará sua confirmação:

WARNING! This will remove:
    - all stopped containers
    - all volumes not used by at least one container
    - all networks not used by at least one container
    - all images without at least one container associated to them
Are you sure you want to continue? [y/N]

Obviamente, essa não é uma resposta direta à pergunta, mas pode salvar algumas vidas ... Isso salvou a minha.

Wallace Sidhrée
fonte
8
acrescentando -a -f torna melhor
Ravi
1
@IulianOnofrei Funciona para mim,Docker version 17.09.0-ce, build afdb6d4
Por Lundberg
1
@ PerLundberg, atualizei dockerpara a mesma versão e funciona, obrigado.
Iulian Onofrei 23/11
1
Isso é um exagero para esse cenário e não é uma resposta utilizável se você não deseja excluir tudo.
M_dk 26/09/19
1
Isso até excluirá as imagens de contêineres parados, provavelmente algo que você não deseja. Versões recentes do docker têm o comando docker builder prunepara limpar as camadas de construção em cache. Apenas caiu na armadilha depois de copiar cegamente os comandos do estouro da pilha.
Evil Azrael
59

O comando docker build --no-cache . resolveu nosso problema semelhante.

Nosso Dockerfile foi:

RUN apt-get update
RUN apt-get -y install php5-fpm

Mas deveria ter sido:

RUN apt-get update && apt-get -y install php5-fpm

Para impedir o armazenamento em cache da atualização e a instalação separadamente.

Consulte: Práticas recomendadas para escrever Dockerfiles

Youniteus
fonte
10
O "deveria ter sido" é enganoso. Se o Docker perceber que possui uma cópia em cache, RUN apt-get update && apt-get -y install php5-fpmvocê ainda o verá sendo reutilizado com o conteúdo antigo.
tripleee
10
Na verdade, ainda faz sentido juntar-se a eles, porque, caso contrário, se você alterar a linha de instalação, ele ainda usará o cache de pacotes antigos, que geralmente terá problemas se o cache estiver desatualizado (geralmente, os arquivos terão 404.)
John Chadwick
19

Para garantir que sua compilação seja totalmente reconstruída, incluindo a verificação de atualizações na imagem base, use as seguintes opções ao compilar:

--no-cache - Isso forçará a reconstrução de camadas já disponíveis

--pull - Isso acionará uma atração da imagem de base referenciada usando FROM, garantindo que você obtenha a versão mais recente.

O comando completo ficará assim:

docker build --pull --no-cache --tag myimage:version .

As mesmas opções estão disponíveis para o docker-compose:

docker-compose build --no-cache --pull
M_dk
fonte
13

Eu não recomendaria usar --no-cacheno seu caso.

Você está executando algumas instalações da etapa 3 a 9 (a propósito, eu preferiria usar um liner) e, se você não quiser a sobrecarga de executar novamente essas etapas sempre que estiver criando sua imagem, modifique o seu Dockerfilecom um passo temporário antes da sua wgetinstrução.

Eu costumo fazer algo como RUN ls . e mudar para RUN ls ./entãoRUN ls ./. e assim por diante para cada modificação feita no arquivo tar recuperado porwget

Obviamente, você pode fazer algo como RUN echo 'test1' > test && rm testaumentar o número 'test1para cada iteração.

Parece sujo, mas, tanto quanto eu sei, é a maneira mais eficiente de continuar se beneficiando do sistema de cache do Docker, que economiza tempo quando você tem muitas camadas ...

Olivier
fonte
3
A capacidade de não usar o cache depois de um certo ponto é um recurso solicitado por muitos (consulte github.com/moby/moby/issues/1996 para obter alternativas para bloqueio de cache)
leszek.hanusz
13

Com o docker-compose, tente docker-compose up -d --build --force-recreate

Yash
fonte
5

A maioria das informações aqui estão corretas.
Aqui está uma compilação deles e minha maneira de usá-los.

A idéia é seguir a abordagem recomendada (criar específico e sem impacto em outros objetos da janela de encaixe) e tentar a abordagem mais radical (não criar específica e com impacto em outros objetos da janela de encaixe) quando não for suficiente.

Abordagem recomendada:

1) Force a execução de cada etapa / instrução no Dockerfile:

docker build --no-cache 

ou com docker-compose build:

docker-compose build --no-cache

Também poderíamos combinar isso com o upsubcomando que recriar todos os contêineres:

docker-compose build --no-cache &&
docker-compose up -d --force-recreate 

Dessa forma, não use cache, mas para o construtor de janelas de encaixe e a imagem base referenciada com a FROMinstrução.

2) Limpe o cache do docker builder (se usarmos o Buildkit, provavelmente precisaremos disso):

docker builder prune -af

3) Se não quisermos usar o cache das imagens pai, podemos tentar excluí-las, como:

docker image rm -f fooParentImage

Na maioria dos casos, essas três coisas são perfeitamente suficientes para permitir uma construção limpa de nossa imagem.
Então, devemos tentar manter isso.

Abordagem mais radical:

Nos casos de canto em que parece que alguns objetos no cache do docker ainda são usados ​​durante a compilação e parecem repetíveis, devemos tentar entender a causa para poder limpar a peça que está faltando de maneira muito específica. Se realmente não encontrarmos uma maneira de reconstruir do zero, existem outras, mas é importante lembrar que elas geralmente excluem muito mais do que o necessário. Portanto, devemos usá-los com cautela geral quando não estamos em um ambiente local / dev.

1) Remova todas as imagens sem pelo menos um contêiner associado a elas:

docker image prune -a

2) Remova muitas outras coisas:

docker system prune -a

Isso diz :

ATENÇÃO! Isso removerá:
  - todos os contêineres parados
  - todas as redes não utilizadas por pelo menos um contêiner
  - todas as imagens sem pelo menos um contêiner associado a elas
  - todo o cache de compilação

O uso desse comando super delete pode não ser suficiente, pois depende muito do estado dos contêineres (em execução ou não). Quando esse comando não é suficiente, tento pensar com cuidado quais contêineres do docker podem causar efeitos colaterais na criação do docker e permitir que esses contêineres sejam encerrados para que possam ser removidos com o comando.

davidxxx
fonte
3

Você pode gerenciar o cache do construtor com docker builder

Para limpar todo o cache sem aviso: docker builder prune -af

Shawn
fonte