Come forzare Docker per una creazione pulita di un'immagine


819

Ho creato un'immagine Docker da un file Docker usando il comando seguente.

$ docker build -t u12_core -f u12_core .

Quando sto cercando di ricostruirlo con lo stesso comando, sta usando la cache di build come:

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <pavan.gupta@gmail.com>
 ---> 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

La cache mostra che aerospike è installato. Tuttavia, non lo trovo all'interno dei container generati da questa immagine, quindi voglio ricostruire questa immagine senza usare la cache. Come posso forzare Docker a ricostruire un'immagine pulita senza cache?


10
A parte questo, dovresti generalmente cercare di ridurre al minimo il numero di RUNdirettive.
Tripleee,

4
@tripleee Puoi spiegare perché?
Ya.

9
@Ya. Una volta Docker creava sempre un livello separato per ogni RUNdirettiva, quindi un Dockerfilecon molte RUNdirettive consumava enormi quantità di spazio su disco; ma questo è apparentemente migliorato un po 'nelle ultime versioni.
tripla il

Quando provo docker-compose up -d, dove posso usare --no-cache?
Oo,

@Oo non è possibile. Devi prima fare docker-compose build --no-cachee poidocker-compose up -d
Martin Melka

Risposte:


1446

C'è --no-cacheun'opzione:

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

Nelle versioni precedenti di Docker era necessario passare --no-cache=true, ma non è più così.


89
Si noti inoltre che --no-cachefunziona con docker-compose build.
Blackus,

42
Potresti anche voler usare --pull. Questo dirà alla finestra mobile di ottenere l'ultima versione dell'immagine di base. Questo è necessario in aggiunta a --no-cachese hai già l'immagine di base (es:) ubuntu/lateste l'immagine di base è stata aggiornata dall'ultima volta che l'hai estratta. Vedi i documenti qui .
Collin Krawll,

2
@CollinKrawll: l' --pullopzione ha fatto il trucco per me. Solo --no-cache, build ancora rotto. Metti anche in --pull, build ha funzionato! Grazie!
Erdős-Bacon,

1
Se qualcuno chiama build docker non si presume che vogliano ricostruire senza cache? In quale caso d'uso qualcuno vorrebbe costruire un'immagine e usare un'immagine precedentemente costruita? <rant> Ho appena perso un giorno perché una build precedente non è riuscita silenziosamente ma è stata completata "correttamente" e stavo usando l'immagine non funzionante per capire perché gli aggiornamenti dello script di build non funzionavano </rant>
Jeff

3
@Jeff Quando stai sviluppando un'immagine docker, la build docker ripeterà solo livelli / passaggi che sono stati modificati. Se ho cinque passaggi e aggiungo un nuovo passaggio all'indice 3, i livelli associati ai passaggi 1 e 2 possono essere riutilizzati. Questo accelera notevolmente il processo di sviluppo
scaglie

130

In alcuni casi estremi, l'unico modo per aggirare gli errori di compilazione ricorrenti è eseguendo:

docker system prune

Il comando ti chiederà la tua conferma:

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]

Questa ovviamente non è una risposta diretta alla domanda, ma potrebbe salvare alcune vite ... Ha salvato la mia.


8
aggiungendo -a -f lo rende migliore
Ravi

1
@IulianOnofrei Funziona per me,Docker version 17.09.0-ce, build afdb6d4
Per Lundberg il

1
@PerLundberg, ho aggiornato dockeralla stessa versione e funziona, grazie.
Iulian Onofrei il

1
Questo è eccessivo per questo scenario e non una risposta utilizzabile se non si desidera eliminare tutto.
M_dk,

1
Questo eliminerà anche le immagini dei contenitori fermi, probabilmente qualcosa che non vuoi. Le versioni recenti della finestra mobile hanno il comando docker builder pruneper cancellare i livelli di build memorizzati nella cache. Appena caduto nella trappola dopo aver copiato ciecamente i comandi dallo stack overflow.
Evil Azrael,

59

Il comando ha docker build --no-cache .risolto il nostro problema simile.

Il nostro Dockerfile era:

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

Ma avrebbe dovuto essere:

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

Per impedire la memorizzazione nella cache dell'aggiornamento e l'installazione separatamente.

Vedi: Best practice per la scrittura di Dockerfile


10
Il "avrebbe dovuto essere" è fuorviante. Se Docker vede che ha una copia cache di RUN apt-get update && apt-get -y install php5-fpmte, vedrebbe comunque che viene riutilizzato con i vecchi contenuti.
Tripleee,

10
In realtà ha ancora senso unirsi a loro, perché altrimenti se cambi la linea di installazione, userà comunque la vecchia cache del pacchetto, che spesso avrà problemi se la cache non è aggiornata (di solito, i file saranno 404.)
John Chadwick

19

Per assicurarti che la tua build sia completamente ricostruita, incluso il controllo dell'immagine di base per gli aggiornamenti, usa le seguenti opzioni durante la compilazione:

--no-cache - Questo costringerà la ricostruzione di livelli già disponibili

--pull - Questo attiverà un pull dell'immagine di base a cui si fa riferimento usando FROM assicurandosi di avere l'ultima versione.

Il comando completo sarà quindi simile al seguente:

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

Le stesse opzioni sono disponibili per la finestra mobile-componi:

docker-compose build --no-cache --pull

13

Non consiglierei di utilizzare --no-cachenel tuo caso.

Stai eseguendo un paio di installazioni dal passaggio 3 al 9 (a proposito, preferirei usare un solo liner) e se non vuoi il sovraccarico di rieseguire questi passaggi ogni volta che stai costruendo la tua immagine puoi modificalo Dockerfilecon un passaggio temporaneo prima delle tue wgetistruzioni.

Uso per fare qualcosa di simile RUN ls .e cambiarlo in RUN ls ./allora RUN ls ./.e così via per ogni modifica fatta sul tarball recuperato dawget

Ovviamente puoi fare qualcosa come RUN echo 'test1' > test && rm testaumentare il numero 'test1per ogni iterazione.

Sembra sporco, ma per quanto ne so è il modo più efficiente per continuare a beneficiare del sistema cache di Docker, che consente di risparmiare tempo quando si hanno molti livelli ...


3
La possibilità di non poter usare la cache dopo un certo punto è una funzione richiesta da molti (vedi github.com/moby/moby/issues/1996 per alternative per il busting della cache)
leszek.hanusz

13

Con prova docker-compose docker-compose up -d --build --force-recreate


6

La maggior parte delle informazioni qui sono corrette.
Ecco una loro raccolta e il mio modo di usarli.

L'idea è quella di attenersi all'approccio raccomandato (costruire specifici e nessun impatto su altri oggetti docker memorizzati) e provare l'approccio più radicale (non costruire specifico e con impatto su altri oggetti docker memorizzati) quando non è sufficiente.

Approccio raccomandato:

1) Forzare l'esecuzione di ogni passo / istruzione nel Dockerfile:

docker build --no-cache 

o con docker-compose build:

docker-compose build --no-cache

Potremmo anche combinarlo con il upcomando secondario che ricrea tutti i contenitori:

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

In questo modo non utilizzare la cache ma per il generatore docker e l'immagine di base a cui si fa riferimento con l' FROMistruzione.

2) Pulisci la cache del generatore docker (se usiamo Buildkit molto probabilmente ne abbiamo bisogno):

docker builder prune -af

3) Se non vogliamo utilizzare la cache delle immagini principali, potremmo provare a eliminarle come:

docker image rm -f fooParentImage

Nella maggior parte dei casi, queste 3 cose sono perfettamente sufficienti per consentire una costruzione chiara della nostra immagine.
Quindi dovremmo cercare di attenerci a questo.

Approccio più radicale:

In casi angolari in cui sembra che alcuni oggetti nella cache docker siano ancora utilizzati durante la compilazione e che sembrano ripetibili, dovremmo cercare di capire la causa per poter cancellare la parte mancante in modo molto specifico. Se davvero non troviamo un modo per ricostruire da zero, ci sono altri modi, ma è importante ricordare che questi generalmente eliminano molto più di quanto sia necessario. Quindi dovremmo usarli con cautela nel complesso quando non siamo in un ambiente locale / di sviluppo.

1) Rimuovere tutte le immagini senza almeno un contenitore ad esse associato:

docker image prune -a

2) Rimuovi molte altre cose:

docker system prune -a

Che dice :

AVVERTIMENTO! Questo rimuoverà:
  - tutti i contenitori fermati
  - tutte le reti non utilizzate da almeno un container
  - tutte le immagini senza almeno un contenitore ad esse associato
  - crea tutta la cache

L'uso di quel comando super-cancellazione potrebbe non essere sufficiente perché dipende fortemente dallo stato dei contenitori (in esecuzione o meno). Quando quel comando non è sufficiente, provo a riflettere attentamente su quali contenitori docker potrebbero causare effetti collaterali alla nostra build docker e consentire a questi container di uscire per consentirne la rimozione con il comando.


3

È possibile gestire la cache del builder con docker builder

Per pulire tutta la cache senza prompt: docker builder prune -af

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.