Jak zmusić Dockera do czystej budowy obrazu

812

Zbudowałem obraz Dockera z pliku Docker za pomocą poniższego polecenia.

$ docker build -t u12_core -f u12_core .

Kiedy próbuję odbudować go za pomocą tego samego polecenia, używa pamięci podręcznej kompilacji, takiej jak:

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

Pamięć podręczna pokazuje, że zainstalowany jest aerospike. Jednak nie znajduję go w pojemnikach spawnowanych z tego obrazu, więc chcę go odbudować bez użycia pamięci podręcznej. Jak zmusić Dockera do odbudowania czystego obrazu bez pamięci podręcznej?

Pavan Gupta
źródło
10
Na marginesie, powinieneś ogólnie spróbować zminimalizować liczbę RUNdyrektyw.
tripleee
4
@tripleee Czy możesz wyjaśnić, dlaczego?
.
9
@Ya. Kiedyś Docker zawsze tworzył osobną warstwę dla każdej RUNdyrektywy, więc Dockerfilewiele RUNdyrektyw zużywałoby gigantyczne ilości miejsca na dysku; ale najwyraźniej zostało to nieco poprawione w ostatnich wersjach.
tripleee
Kiedy próbuję docker-compose up -d, gdzie mogę użyć --no-cache?
Oo
@Oo, to niemożliwe. Najpierw musisz to zrobić, docker-compose build --no-cachea potemdocker-compose up -d
Martin Melka

Odpowiedzi:

1438

Istnieje --no-cacheopcja:

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

W starszych wersjach Dockera trzeba było przejść --no-cache=true, ale już tak nie jest.

Assaf Lavie
źródło
87
Zauważ też, że --no-cachedziała z docker-compose build.
Blackus
42
Możesz także użyć --pull. Dzięki temu doker otrzyma najnowszą wersję obrazu podstawowego. Jest to konieczne dodatkowo, --no-cachejeśli masz już obraz podstawowy (np .:), ubuntu/latesta obraz podstawowy został zaktualizowany od czasu ostatniego pobrania. Zobacz dokumenty tutaj .
Collin Krawll,
2
@CollinKrawll: Ta --pullopcja załatwiła sprawę . Po prostu --no-cachekompilacja wciąż się zepsuła. Wstaw --pullteż, kompilacja działa! Dziękuję Ci!
Erdős-Bacon
1
Jeśli ktoś dzwoni do kompilacji dokera, czy nie zakłada się, że chce odbudować bez pamięci podręcznej? W jakim przypadku użycia ktoś chciałby zbudować obraz i użyć wcześniej zbudowanego obrazu? <rant> Właśnie straciłem dzień, ponieważ wcześniejsza kompilacja po cichu zakończyła się niepowodzeniem, ale zakończyła się „sukcesem” i korzystałem z uszkodzonego obrazu, nie rozumiejąc, dlaczego aktualizacje skryptu kompilacji nie działały </rant>
Jeff
3
@Jeff Podczas opracowywania obrazu dokera, kompilacja dokera będzie ponawiać tylko zmodyfikowane warstwy / kroki. Jeśli mam pięć kroków i dodam nowy krok o indeksie 3, warstwy związane z krokami 1 i 2 mogą być ponownie użyte. To znacznie przyspiesza proces rozwoju
płatki
129

W niektórych ekstremalnych przypadkach jedynym sposobem na obejście powtarzających się błędów kompilacji jest uruchomienie:

docker system prune

Polecenie poprosi o potwierdzenie:

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]

To oczywiście nie jest bezpośrednia odpowiedź na pytanie, ale może uratować życie… Uratowało moje.

Wallace Sidhrée
źródło
8
dodanie -a -f czyni to lepszym
Ravi
1
@IulianOnofrei Pracuje dla mnie,Docker version 17.09.0-ce, build afdb6d4
Per Lundberg
1
@PerLundberg, zaktualizowałem dockerdo tej samej wersji i działa, dziękuję.
Iulian Onofrei
1
Jest to zdecydowanie przesada w tym scenariuszu i nie jest użyteczną odpowiedzią, jeśli nie chcesz usunąć wszystkiego.
M_dk
1
Spowoduje to nawet usunięcie obrazów zatrzymanych pojemników, prawdopodobnie czegoś, czego nie chcesz. Najnowsze wersje dokera mają polecenie docker builder prunewyczyszczenia buforowanych warstw kompilacji. Właśnie wpadłem w pułapkę po ślepym skopiowaniu poleceń z przepełnienia stosu.
Zły Azrael
59

Polecenie docker build --no-cache .rozwiązało nasz podobny problem.

Nasz plik Dockerfile to:

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

Ale powinno być:

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

Aby zapobiec buforowaniu aktualizacji i instalacji osobno.

Zobacz: Najlepsze praktyki pisania Dockerfiles

Youniteus
źródło
10
Słowo „powinno być” wprowadza w błąd. Jeśli Docker zobaczy, że ma kopię w pamięci podręcznej RUN apt-get update && apt-get -y install php5-fpm, nadal zobaczy, że zostanie ona ponownie wykorzystana ze starą zawartością.
tripleee
10
Właściwie nadal ma sens dołączanie do nich, ponieważ w przeciwnym razie, jeśli zmienisz linię instalacyjną, nadal będzie używać starej pamięci podręcznej pakietu, co często będzie miało problemy, jeśli pamięć podręczna będzie nieaktualna (zwykle pliki będą 404.)
John Chadwick
18

Aby upewnić się, że twoja kompilacja została całkowicie przebudowana, w tym sprawdzenie obrazu podstawowego w poszukiwaniu aktualizacji, podczas budowania użyj następujących opcji:

--no-cache - Wymusi to przebudowę już dostępnych warstw

--pull - Spowoduje to przyciągnięcie obrazu podstawowego, do którego odwołuje się FROM, upewniając się, że masz najnowszą wersję.

Pełne polecenie będzie zatem wyglądać następująco:

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

Te same opcje są dostępne w przypadku dokowania-tworzenia:

docker-compose build --no-cache --pull
M_dk
źródło
13

Nie polecam używania --no-cachew twoim przypadku.

Prowadzisz kilka instalacji od kroku 3 do 9 (nawiasem mówiąc, wolałbym używać jednego linera) i jeśli nie chcesz nakładać się na ponowne uruchamianie tych kroków za każdym razem, gdy budujesz swój obraz, możesz zmodyfikuj swój Dockerfiletymczasowym krokiem przed wgetinstrukcją.

Robię coś podobnego RUN ls .i zmieniam na RUN ls ./to RUN ls ./.i tak dalej dla każdej modyfikacji wykonanej na tarballu pobranym przezwget

Możesz oczywiście zrobić coś takiego jak RUN echo 'test1' > test && rm testzwiększenie liczby 'test1dla każdej iteracji.

Wygląda na brudną, ale o ile wiem, jest to najbardziej skuteczny sposób na dalsze korzystanie z systemu pamięci podręcznej Docker, który oszczędza czas, gdy masz wiele warstw ...

Olivier
źródło
3
Zdolność do nieużywania pamięci podręcznej po pewnym momencie jest funkcją wymaganą przez wielu (patrz github.com/moby/moby/issues/1996, aby znaleźć alternatywę dla pomijania pamięci podręcznej)
leszek.hanusz
13

Z próbą skompilowania dokera docker-compose up -d --build --force-recreate

Yash
źródło
5

Większość informacji tutaj jest poprawna.
Oto ich zestawienie i mój sposób ich wykorzystania.

Chodzi o to, aby trzymać się zalecanego podejścia (budowanie specyficznego i bez wpływu na inne przechowywane obiekty dokera) i wypróbować bardziej radykalne podejście (nie budować specyficznie i z wpływem na inne przechowywane obiekty dokera), kiedy to nie wystarczy.

Zalecane podejście:

1) Wymuś wykonanie każdego kroku / instrukcji w Dockerfile:

docker build --no-cache 

lub z docker-compose build:

docker-compose build --no-cache

Możemy to również połączyć z poleceniem uppodrzędnym, które odtwarza wszystkie kontenery:

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

W ten sposób nie używaj pamięci podręcznej, ale dla konstruktora dokera i obrazu podstawowego, do którego odwołuje się FROMinstrukcja.

2) Wyczyść pamięć podręczną konstruktora dokerów (jeśli korzystamy z Buildkit, najprawdopodobniej potrzebujemy tego):

docker builder prune -af

3) Jeśli nie chcemy używać pamięci podręcznej obrazów nadrzędnych, możemy spróbować je usunąć, na przykład:

docker image rm -f fooParentImage

W większości przypadków te 3 rzeczy są całkowicie wystarczające, aby umożliwić czystą budowę naszego obrazu.
Powinniśmy więc starać się tego trzymać.

Bardziej radykalne podejście:

W przypadkach narożnych, w których wydaje się, że niektóre obiekty w pamięci podręcznej dokera są nadal używane podczas kompilacji i które wyglądają na powtarzalne, powinniśmy spróbować zrozumieć przyczynę, aby móc bardzo dokładnie wyczyścić brakującą część. Jeśli naprawdę nie znajdziemy sposobu na odbudowę od zera, istnieją inne sposoby, ale ważne jest, aby pamiętać, że na ogół usuwają one znacznie więcej, niż jest to wymagane. Dlatego powinniśmy używać ich ostrożnie, gdy nie jesteśmy w środowisku lokalnym / deweloperskim.

1) Usuń wszystkie obrazy bez co najmniej jednego skojarzonego z nimi pojemnika:

docker image prune -a

2) Usuń wiele innych rzeczy:

docker system prune -a

To mówi:

OSTRZEŻENIE! Spowoduje to usunięcie:
  - wszystkie zatrzymane pojemniki
  - wszystkie sieci nieużywane przez co najmniej jeden kontener
  - wszystkie obrazy bez co najmniej jednego skojarzonego z nimi pojemnika
  - cała pamięć podręczna kompilacji

Użycie tej komendy super delete może być niewystarczające, ponieważ silnie zależy od stanu kontenerów (uruchomionych lub nie). Kiedy to polecenie nie wystarcza, staram się dokładnie przemyśleć, które kontenery dokerów mogą powodować skutki uboczne w naszej kompilacji dokerów i pozwolić, aby te kontenery zostały opuszczone w celu umożliwienia ich usunięcia za pomocą komendy.

davidxxx
źródło
3

Możesz zarządzać pamięcią podręczną konstruktora za pomocą docker builder

Aby wyczyścić całą pamięć podręczną bez monitu: docker builder prune -af

Shawn
źródło