Mój plik Dockerfile jest podobny do
FROM my/base
ADD . /srv
RUN pip install -r requirements.txt
RUN python setup.py install
ENTRYPOINT ["run_server"]
Za każdym razem, gdy tworzę nowy obraz, zależności muszą być ponownie instalowane, co może być bardzo powolne w moim regionie.
Jednym ze sposobów, w jaki myślę o cache
pakietach, które zostały zainstalowane, jest zastąpienie my/base
obrazu nowszymi obrazami, takimi jak ten:
docker build -t new_image_1 .
docker tag new_image_1 my/base
Więc następnym razem, gdy będę budować z tym plikiem Dockerfile, mój / base ma już zainstalowane pakiety.
Ale to rozwiązanie ma dwa problemy:
- Nie zawsze jest możliwe zastąpienie obrazu podstawowego
- Obraz podstawowy staje się coraz większy w miarę nakładania na niego nowszych obrazów
Więc jakie lepsze rozwiązanie mógłbym użyć do rozwiązania tego problemu?
EDYTOWAĆ##:
Niektóre informacje o dokerze na moim komputerze:
☁ test docker version
Client version: 1.1.2
Client API version: 1.13
Go version (client): go1.2.1
Git commit (client): d84a070
Server version: 1.1.2
Server API version: 1.13
Go version (server): go1.2.1
Git commit (server): d84a070
☁ test docker info
Containers: 0
Images: 56
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Dirs: 56
Execution Driver: native-0.2
Kernel Version: 3.13.0-29-generic
WARNING: No swap limit support
my/base
Odpowiedzi:
Spróbuj zbudować plik Dockerfile, który wygląda mniej więcej tak:
Docker będzie używał pamięci podręcznej podczas instalacji pip, o ile nie wprowadzisz żadnych zmian w
requirements.txt
pliku, niezależnie od tego, czy inne pliki kodu w witrynie.
zostały zmienione, czy nie. Oto przykład.Oto prosty
Hello, World!
program:Dane wyjściowe kompilacji dockera:
Zmodyfikujmy
run.py
:Spróbuj ponownie zbudować, poniżej jest wynik:
Jak widać powyżej, tym razem docker używa pamięci podręcznej podczas kompilacji. Teraz zaktualizujmy
requirements.txt
:Poniżej znajduje się wynik kompilacji dockera:
Zwróć uwagę, że docker nie używał pamięci podręcznej podczas instalacji pip. Jeśli to nie zadziała, sprawdź wersję dockera.
źródło
ADD
instrukcję, pamięć podręczna jest unieważniana.ADD ./requirements.txt /srv/requirements.txt
), wtedy docker musi używać cache. Zobacz add seciton on Dockerfile document.ADD requirements.txt /srv
przed uruchomieniem pip (RUN pip install -r requirements.txt
) i dodaniem wszystkich innych plików po uruchomieniu pip. Dlatego powinny one być w następującej kolejności: (1)ADD requirements.txt /srv
; (2)RUN pip install -r requirements.txt
; ( 3)ADD . /srv
Aby zminimalizować aktywność sieciową, możesz wskazać
pip
katalog pamięci podręcznej na komputerze głównym.Uruchom kontener Docker z powiązaniem katalogu pamięci podręcznej pip hosta podłączonym do katalogu pamięci podręcznej pip kontenera.
docker run
polecenie powinno wyglądać następująco:Następnie w pliku Dockerfile zainstaluj wymagania jako część
ENTRYPOINT
instrukcji (lubCMD
instrukcji), a nie jakoRUN
polecenie. Jest to ważne, ponieważ (jak wskazano w komentarzach) mount nie jest dostępny podczas budowania obrazu (podczasRUN
wykonywania instrukcji). Plik Dockera powinien wyglądać następująco:źródło
Rozumiem, że to pytanie ma już kilka popularnych odpowiedzi. Ale jest nowszy sposób buforowania plików dla menedżerów pakietów. Myślę, że może to być dobra odpowiedź w przyszłości, gdy BuildKit stanie się bardziej standardowy.
Od Dockera 18.09 dostępna jest eksperymentalna obsługa BuildKit . BuildKit dodaje obsługę niektórych nowych funkcji w pliku Dockerfile, w tym eksperymentalną obsługę montażu woluminów zewnętrznych w
RUN
krokach. To pozwala nam tworzyć pamięci podręczne dla rzeczy takich jak$HOME/.cache/pip/
.requirements.txt
Jako przykładu użyjemy następującego pliku:Typowy przykład Pythona
Dockerfile
może wyglądać następująco:Po włączeniu BuildKit przy użyciu
DOCKER_BUILDKIT
zmiennej środowiskowej możemy zbudować niezbuforowanypip
krok w około 65 sekund:Teraz dodajmy eksperymentalny nagłówek i zmodyfikujmy
RUN
krok, aby buforować pakiety Pythona:Śmiało i zrób teraz kolejną kompilację. Powinno to zająć tyle samo czasu. Ale tym razem buforuje pakiety Pythona w naszym nowym montowaniu pamięci podręcznej:
Około 60 sekund. Podobnie jak w naszej pierwszej kompilacji.
Wprowadź niewielką zmianę w
requirements.txt
(na przykład dodanie nowej linii między dwoma pakietami), aby wymusić unieważnienie pamięci podręcznej i uruchomić ponownie:Tylko około 16 sekund!
Otrzymujemy to przyspieszenie, ponieważ nie pobieramy już wszystkich pakietów Pythona. Zostały buforowane przez menedżera pakietów (
pip
w tym przypadku) i przechowywane w woluminie pamięci podręcznej. Montaż woluminu jest dostarczany do kroku uruchamiania, dzięki czemupip
można ponownie wykorzystać nasze już pobrane pakiety. Dzieje się to poza buforowaniem warstwy Dockera .Zyski powinny być znacznie lepsze na większych
requirements.txt
.Uwagi:
Kompilacja BuildKit nie działa w Docker Compose ani w innych narzędziach, które w tej chwili bezpośrednio używają API Dockera.Jest to teraz obsługiwane w Docker Compose od 1.25.0. Zobacz, jak włączyć BuildKit za pomocą docker-compose?docker system prune -a
.Miejmy nadzieję, że te funkcje zostaną wprowadzone do Dockera do budowania, a BuildKit stanie się domyślnym. Jeśli tak się stanie, spróbuję zaktualizować tę odpowiedź.
źródło
Dockerfile
lub wersja Dockera jest za stara. Utworzyłbym nowe pytanie ze wszystkimi informacjami dotyczącymi debugowania.Zauważyłem, że lepszym sposobem jest po prostu dodanie katalogu pakietów witryn Pythona jako woluminu.
W ten sposób mogę po prostu zainstalować nowe biblioteki za pomocą pip bez konieczności wykonywania pełnej przebudowy.
EDYCJA : Zignoruj tę odpowiedź, odpowiedź jkukul powyżej działała dla mnie. Moim zamiarem było buforowanie folderu pakietów witryn . To wyglądałoby bardziej jak:
Buforowanie folderu pobierania jest jednak znacznie czystsze. To również buforuje koła, więc poprawnie wykonuje zadanie.
źródło