Mój DockerFile to coś takiego
FROM my/base
ADD . /srv
RUN pip install -r requirements.txt
RUN python setup.py install
ENTRYPOINT ["run_server"]
Za każdym razem, gdy zbuduję nowy obraz, zależności muszą być ponownie zainstalowane, co może być bardzo powolne w moim regionie.
Jeden sposób, w jaki pomyślę, że zainstalowano cache
, jest zastąpienie obrazu my/base
z nowszymi obrazami:
docker build -t new_image_1 .
docker tag new_image_1 my/base
Więc następnym razem, gdy zbuduję z tym Dockerfile, moja / baza ma już zainstalowane pakiety.
Ale to rozwiązanie ma dwa problemy:
- Nie zawsze jest możliwe zastąpienie podstawowego obrazu
- Obraz bazowy rośnie większy i większy, ponieważ nowsze obrazy są na nim warstwowe
Więc jakie lepsze rozwiązanie mogłem użyć do rozwiązania tego problemu?
EDYTOWAĆ##:
Niektóre informacje o dokowaniu na mojej maszynie:
☁ 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
4 odpowiedzi
Spróbuj zbudować z poniższym Dockerfile.
FROM my/base
WORKDIR /srv
ADD ./requirements.txt /srv/requirements.txt
RUN pip install -r requirements.txt
ADD . /srv
RUN python setup.py install
ENTRYPOINT ["run_server"]
Jeśli są pewne zmiany w .
(twój projekt), doker Skip pip install
za pomocą pamięci podręcznej.
Dokument Uruchom tylko pip install
na kompilacji podczas edycji Wymańców.txt.
Piszę prosty program {x0}}.
$ tree
.
├── Dockerfile
├── requirements.txt
└── run.py
0 directories, 3 file
# Dockerfile
FROM dockerfile/python
WORKDIR /srv
ADD ./requirements.txt /srv/requirements.txt
RUN pip install -r requirements.txt
ADD . /srv
CMD python /srv/run.py
# requirements.txt
pytest==2.3.4
# run.py
print("Hello, World")
Poniżej znajduje się wyjście.
Step 1 : WORKDIR /srv
---> Running in 22d725d22e10
---> 55768a00fd94
Removing intermediate container 22d725d22e10
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> 968a7c3a4483
Removing intermediate container 5f4e01f290fd
Step 3 : RUN pip install -r requirements.txt
---> Running in 08188205e92b
Downloading/unpacking pytest==2.3.4 (from -r requirements.txt (line 1))
Running setup.py (path:/tmp/pip_build_root/pytest/setup.py) egg_info for package pytest
....
Cleaning up...
---> bf5c154b87c9
Removing intermediate container 08188205e92b
Step 4 : ADD . /srv
---> 3002a3a67e72
Removing intermediate container 83defd1851d0
Step 5 : CMD python /srv/run.py
---> Running in 11e69b887341
---> 5c0e7e3726d6
Removing intermediate container 11e69b887341
Successfully built 5c0e7e3726d6
Zaktualizuję tylko run.py i spróbuj ponownie zbudować.
# run.py
print("Hello, Python")
Poniżej znajduje się wyjście.
Sending build context to Docker daemon 5.12 kB
Sending build context to Docker daemon
Step 0 : FROM dockerfile/python
---> f86d6993fc7b
Step 1 : WORKDIR /srv
---> Using cache
---> 55768a00fd94
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> Using cache
---> 968a7c3a4483
Step 3 : RUN pip install -r requirements.txt
---> Using cache
---> bf5c154b87c9
Step 4 : ADD . /srv
---> 9cc7508034d6
Removing intermediate container 0d7cf71eb05e
Step 5 : CMD python /srv/run.py
---> Running in f25c21135010
---> 4ffab7bc66c7
Removing intermediate container f25c21135010
Successfully built 4ffab7bc66c7
Jak widać powyżej, doker używa pamięci podręcznej. I tym razem aktualizuję wymagania.
# requirements.txt
pytest==2.3.4
ipython
Poniżej znajduje się wyjście.
Sending build context to Docker daemon 5.12 kB
Sending build context to Docker daemon
Step 0 : FROM dockerfile/python
---> f86d6993fc7b
Step 1 : WORKDIR /srv
---> Using cache
---> 55768a00fd94
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> b6c19f0643b5
Removing intermediate container a4d9cb37dff0
Step 3 : RUN pip install -r requirements.txt
---> Running in 4b7a85a64c33
Downloading/unpacking pytest==2.3.4 (from -r requirements.txt (line 1))
Running setup.py (path:/tmp/pip_build_root/pytest/setup.py) egg_info for package pytest
Downloading/unpacking ipython (from -r requirements.txt (line 2))
Downloading/unpacking py>=1.4.12 (from pytest==2.3.4->-r requirements.txt (line 1))
Running setup.py (path:/tmp/pip_build_root/py/setup.py) egg_info for package py
Installing collected packages: pytest, ipython, py
Running setup.py install for pytest
Installing py.test script to /usr/local/bin
Installing py.test-2.7 script to /usr/local/bin
Running setup.py install for py
Successfully installed pytest ipython py
Cleaning up...
---> 23a1af3df8ed
Removing intermediate container 4b7a85a64c33
Step 4 : ADD . /srv
---> d8ae270eca35
Removing intermediate container 7f003ebc3179
Step 5 : CMD python /srv/run.py
---> Running in 510359cf9e12
---> e42fc9121a77
Removing intermediate container 510359cf9e12
Successfully built e42fc9121a77
A Docker nie używa build Cache. Jeśli to nie zadziała, sprawdź wersję dokera.
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
Rozumiem, że to pytanie ma już jakieś popularne odpowiedzi. Ale jest nowsza droga do pamięci podręcznej dla menedżerów pakietów. Myślę, że może być dobrą odpowiedzią w przyszłości, gdy Buildkit staje się bardziej standardowy.
Od Docker 18.09 Istnieje wsparcie eksperymentalne dla Buildkit. Buildkit dodaje wsparcia dla niektórych nowych funkcji w Dockerfile, w tym Eksperymentalny Obsługa montażu zewnętrznych woluminów do RUN
. Pozwala nam to tworzyć bufory dla rzeczy takich jak $HOME/.cache/pip/
.
Korzystamy z poniższego pliku requirements.txt
jako przykład:
Click==7.0
Django==2.2.3
django-appconf==1.0.3
django-compressor==2.3
django-debug-toolbar==2.0
django-filter==2.2.0
django-reversion==3.0.4
django-rq==2.1.0
pytz==2019.1
rcssmin==1.0.6
redis==3.3.4
rjsmin==1.1.0
rq==1.1.0
six==1.12.0
sqlparse==0.3.0
Typowy przykład Python Dockerfile
może wyglądać jak:
FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip install -r requirements.txt
COPY . /usr/src/app
Dzięki Buildkit włączone przy użyciu zmiennej środowiskowej DOCKER_BUILDKIT
możemy zbudować nieświdził pip
krok w około 65 sekund:
$ export DOCKER_BUILDKIT=1
$ docker build -t test .
[+] Building 65.6s (10/10) FINISHED
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load metadata for docker.io/library/python:3.7 0.5s
=> CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092 0.0s
=> [internal] load build context 0.6s
=> => transferring context: 899.99kB 0.6s
=> CACHED [internal] helper image for file operations 0.0s
=> [2/4] COPY requirements.txt /usr/src/app/ 0.5s
=> [3/4] RUN pip install -r requirements.txt 61.3s
=> [4/4] COPY . /usr/src/app 1.3s
=> exporting to image 1.2s
=> => exporting layers 1.2s
=> => writing image sha256:d66a2720e81530029bf1c2cb98fb3aee0cffc2f4ea2aa2a0760a30fb718d7f83 0.0s
=> => naming to docker.io/library/test 0.0s
Teraz dodajmy eksperymentalny nagłówek i zmodyfikuj RUN
Krok, aby podręczać pakiety Python:
# syntax=docker/dockerfile:experimental
FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
COPY . /usr/src/app
Idź dalej i wykonaj kolejną budowę. Powinien zajmować taką samą ilość czasu. Ale tym razem buforowanie pakietów Pythona w naszym nowym uchwycie pamięci podręcznej:
$ docker build -t pythontest .
[+] Building 60.3s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:experimental 0.5s
=> CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:9022e911101f01b2854c7a4b2c77f524b998891941da55208e71c0335e6e82c3 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load metadata for docker.io/library/python:3.7 0.5s
=> CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092 0.0s
=> [internal] load build context 0.7s
=> => transferring context: 899.99kB 0.6s
=> CACHED [internal] helper image for file operations 0.0s
=> [2/4] COPY requirements.txt /usr/src/app/ 0.6s
=> [3/4] RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt 53.3s
=> [4/4] COPY . /usr/src/app 2.6s
=> exporting to image 1.2s
=> => exporting layers 1.2s
=> => writing image sha256:0b035548712c1c9e1c80d4a86169c5c1f9e94437e124ea09e90aea82f45c2afc 0.0s
=> => naming to docker.io/library/test 0.0s
Około 60 sekund. Podobny do naszej pierwszej kompilacji.
Zrób mała zmiana do requirements.txt
(np. Dodawanie nowej linii między dwoma pakietami), aby zmusić unieważnienie i uruchomienie pamięci podręcznej:
$ docker build -t pythontest .
[+] Building 15.9s (14/14) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:experimental 1.1s
=> CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:9022e911101f01b2854c7a4b2c77f524b998891941da55208e71c0335e6e82c3 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 120B 0.0s
=> [internal] load .dockerignore 0.0s
=> [internal] load metadata for docker.io/library/python:3.7 0.5s
=> CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092 0.0s
=> CACHED [internal] helper image for file operations 0.0s
=> [internal] load build context 0.7s
=> => transferring context: 899.99kB 0.7s
=> [2/4] COPY requirements.txt /usr/src/app/ 0.6s
=> [3/4] RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt 8.8s
=> [4/4] COPY . /usr/src/app 2.1s
=> exporting to image 1.1s
=> => exporting layers 1.1s
=> => writing image sha256:fc84cd45482a70e8de48bfd6489e5421532c2dd02aaa3e1e49a290a3dfb9df7c 0.0s
=> => naming to docker.io/library/test 0.0s
Tylko około 16 sekund!
Dostajemy ten speedup, ponieważ nie pobieramy już wszystkich pakietów Python. W tym przypadku były buforowane przez menedżera pakietów (pip
w tym przypadku) i przechowywane w uchwycie głośności pamięci podręcznej. Montaż głośności jest dostarczany do kroku Uruchom, aby pip
może ponownie wykorzystać nasze już pobrane pakiety. dzieje się to poza dowolnym buforowaniem warstwy Docker .
Zyski powinny być znacznie lepiej na większym {x0}}.
Uwagi:
- Jest to eksperymentalna składnia Dockerfile i powinna być traktowana jako taka. Nie możesz w tej chwili nie chcesz zbudować w produkcji.
Stuff Buildkit nie działa pod dokującym komponować lub innych narzędzi, które bezpośrednio korzystają z API Docker w tej chwili. Zobacz Jak włączyć Buildkit z Docker-Compose?- W tej chwili nie ma żadnego bezpośredniego interfejsu zarządzanego w pamięci podręcznej. Jest oczyszczony, gdy wykonasz
docker system prune -a
.
Mam nadzieję, że te funkcje sprawią, że do dokika do budynku i Buildkit stanie się domyślnie. Jeśli tak się stanie, spróbuję zaktualizować tę odpowiedź.
Aby zminimalizować aktywność sieci, możesz wskazać pip
do katalogu pamięci podręcznej na komputerze hosta.
Uruchom kontener Docker z katalogiem pamięci podręcznej hosta, wiązane w katalogu pamięci podręcznej na kontenera. docker run
polecenie powinno wyglądać tak:
docker run -v $HOME/.cache/pip/:/root/.cache/pip image_1
Następnie w swoim DockerFile Zainstaluj swoje wymagania jako część ENTRYPOINT
instrukcja (lub {x1}} instrukcja) zamiast polecenia RUN
. Jest to ważne, ponieważ (jak wskazano w komentarzach) Góra nie jest dostępna podczas budynku obrazu (gdy wykonywane są RUN
instrukcje). Plik Docker powinien wyglądać tak:
FROM my/base
ADD . /srv
ENTRYPOINT ["sh", "-c", "pip install -r requirements.txt && python setup.py install && run_server"]
Prawdopodobnie najlepiej, jeśli domyślny katalog PIP systemu hosta zostanie użyty jako pamięć podręczna (np
Odkryłem, że lepszym sposobem jest po prostu dodanie katalogu pakietów witryn Pythona jako wolumin.
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
- /usr/local/lib/python2.7/site-packages/
W ten sposób mogę tylko zainstalować nowe biblioteki bez konieczności wykonywania pełnej przebudowy.
Edytuj : Zignoruj tę odpowiedź, JKUKUL's powyżej przepracowany dla mnie. Moim zamiarem było podbicie folderu w witrynie . To wyglądałoby coś więcej:
volumes:
- .:/code
- ./cached-packages:/usr/local/lib/python2.7/site-packages/
Caching folder pobierania jest jednak czyszczeniem. To również buzi się koła, więc właściwie osiąga zadanie.
Podobne pytania
Powiązane pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.