Docker ADD vs VOLUME

116

Uczę się Dockera i mam wątpliwości, kiedy i gdzie używać ADDi VOLUME. Oto, co myślę, że oba z nich robią:

DODAJ

Skopiuj pliki do obrazu w czasie kompilacji. Obraz zawiera wszystkie pliki, dzięki czemu można je bardzo łatwo wdrożyć. Z drugiej strony, konieczność kompilowania za każdym razem nie wygląda na dobry pomysł w programowaniu, ponieważ budowanie wymaga od dewelopera uruchomienia polecenia przebudowania kontenera; dodatkowo budowanie kontenera może być czasochłonne.

TOM

Rozumiem, że za pomocą docker run -vmożesz zamontować folder hosta w swoim kontenerze, w ten sposób możesz łatwo modyfikować pliki i obserwować, jak aplikacja w Twoim kontenerze reaguje na zmiany. Wygląda świetnie w programowaniu, ale nie jestem pewien, jak wdrożyć moje pliki w ten sposób.

Cristian Garcia
źródło
3
W ogóle, to najlepiej jest wolą COPYsię ADD. Są prawie takie same, ale ADDmają dodatkowe możliwości zapisywania adresów URL i plików archiwów, które mogą być zaskakujące.
Adrian Mouat,
2
@jamesmstone - ten link (i oficjalne dokumenty dockera) zalecają coś przeciwnego - użyj KOPIUJ zamiast DODAJ.
Inżynier oprogramowania,
ups, masz rację - pozdrawiam!
jamesmstone,

Odpowiedzi:

183

DODAJ

Podstawowa różnica między tymi dwoma polega na tym, ADDże wszystko, co dodajesz, czy to folder, czy tylko plik, jest w rzeczywistości częścią obrazu . Każdy, kto użyje utworzonego później obrazu, będzie miał dostęp do wszystkiego, co Ty ADD. Dzieje się tak, nawet jeśli później go usuniesz, ponieważ Docker działa w warstwach, a ADDwarstwa będzie nadal istnieć jako część obrazu. Żeby było jasne, ADDcoś jest tylko w czasie kompilacji i nigdy nie możesz ADDw czasie wykonywania.

Kilka przykładów przypadków, w których chciałbyś użyć ADD:

  • Masz pewne wymagania w pliku Requirements.txt, do którego chcesz się odwołać i zainstalować w pliku Dockerfile. Możesz wtedy zrobić: ADD ./requirements.txt /requirements.txta następnieRUN pip install -r /requirements.txt
  • Chcesz użyć kodu aplikacji jako kontekstu w pliku Dockerfile, na przykład, jeśli chcesz ustawić katalog aplikacji jako katalog roboczy w obrazie i mieć domyślne polecenie w kontenerze uruchamiane z obrazu, aby faktycznie uruchomić aplikację, potrafi:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

TOM

Z drugiej strony, wolumin po prostu pozwala kontenerowi uruchamianemu z twojego obrazu mieć dostęp do jakiejś ścieżki na dowolnym komputerze lokalnym, na którym jest uruchamiany kontener. Nie możesz używać plików z VOLUMEkatalogu w pliku Dockerfile . Wszystko w katalogu woluminu nie będzie dostępne w czasie kompilacji, ale będzie dostępne w czasie wykonywania .

Kilka przykładów przypadków, w których chciałbyś użyć VOLUME:

  • Aplikacja uruchamiana w Twoim kontenerze dokonuje logowania /var/log/my_app. Chcesz, aby te dzienniki były dostępne na komputerze hosta i nie były usuwane po usunięciu kontenera. Możesz to zrobić, tworząc punkt montowania w /var/log/my_app, dodając VOLUME /var/log/my_appdo pliku Dockerfile, a następnie uruchamiając kontener zdocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • Masz kilka plików ustawień lokalnych, do których aplikacja w kontenerze ma mieć dostęp. Być może te pliki ustawień są inne na komputerze lokalnym, niż w wersji deweloperskiej i produkcyjnej. Zwłaszcza jeśli te pliki ustawień są tajne, w takim przypadku zdecydowanie nie chcesz ich na swoim obrazie . W takim przypadku dobrą strategią jest dodanie VOLUME /etc/settings/my_app_settingsdo pliku Dockerfile, uruchomienie kontenera docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tagi upewnienie się, że / host / settings / dir istnieje we wszystkich środowiskach, w których spodziewasz się uruchomienia aplikacji.
Eli
źródło
13
Zdecydowanie najbardziej przydatny post, jaki do tej pory znalazłem w ADD and VOLUME
Jasmeet
5
Co się stanie, jeśli podana zostanie OBJĘTOŚĆ, ale nie zostanie ona podana podczas uruchamiania platformy Docker (np. Brakuje parametru -v xxx)? Czy resp. OBJĘTOŚĆ staje się wtedy faktycznie przejściowa?
kol. Panic
Wewnątrz pliku Dockerfile woluminy są prawdopodobnie przeznaczone tylko do trwałości i / lub debugowania, ale możesz użyć przełącznika wiersza poleceń głośności, aby pobrać aplikację do istniejącego obrazu (nie jest potrzebny plik Dockerfile) i uruchomić ją w ten sposób docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro
ładny szczegół „warstwy”
stratovarius,
27

VOLUMEInstrukcja tworzy wolumin danych w kontenerze Docker przy starcie. Katalog podany jako argument VOLUMEto katalog, który pomija Union File System i jest używany głównie do przechowywania trwałych i udostępnianych danych.

Jeśli uruchomisz docker inspect <your-container>, zobaczysz pod Mountssekcją, Sourcektóra reprezentuje lokalizację katalogu na hoście i Destinationktóra reprezentuje lokalizację zamontowanego katalogu w kontenerze. Na przykład,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

Oto 3 przypadki użycia docker run -v:

  1. docker run -v /data: Jest to analogiczne do określenia VOLUMEinstrukcji w pliku Dockerfile.
  2. docker run -v $host_path:$container_path: Pozwala to na instalację $host_pathz hosta do $container_pathkontenera w czasie wykonywania. W programowaniu jest to przydatne do udostępniania kodu źródłowego na hoście z kontenerem. W środowisku produkcyjnym można to wykorzystać do zamontowania /etc/resolv.confw kontenerze takich rzeczy, jak informacje DNS hosta (znalezione w ) lub sekrety. I odwrotnie, możesz również użyć tej techniki do zapisania dzienników kontenera w określonych folderach na hoście. Obie $host_pathi $container_pathmuszą być ścieżkami absolutnymi.
  3. docker run -v my_volume:$container_path: Spowoduje to utworzenie wolumenu danych w kontenerze w lokalizacji $container_pathi nazwanie go my_volume. Zasadniczo jest to to samo, co tworzenie i nazywanie wolumenu przy użyciu docker volume create my_volume. Takie nazwanie woluminu jest przydatne w przypadku woluminu danych kontenera i woluminu pamięci współużytkowanej przy użyciu sterownika pamięci masowej dla wielu hostów, takiego jak Flocker .

Zwróć uwagę, że podejście polegające na zamontowaniu folderu hosta jako woluminu danych nie jest dostępne w pliku Dockerfile. Cytując dokumentację Dockera ,

Uwaga: nie jest to dostępne w pliku Dockerfile ze względu na jego przenośność i cel udostępniania. Ponieważ katalog hosta jest z natury zależny od hosta, katalog hosta określony w pliku Dockerfile prawdopodobnie nie działałby na wszystkich hostach.

Teraz, jeśli chcesz skopiować pliki do kontenerów w środowiskach innych niż programistyczne, możesz użyć instrukcji ADDlub COPYw pliku Dockerfile. To jest to, czego zwykle używam do wdrażania innych niż programistyczne.

ivan.sim
źródło
3
Czy powinienem utworzyć 2 pliki Dockera? Jeden do programowania, a drugi do wdrażania?
Cristian Garcia
Nie sądzę. Nie ma nic złego w posiadaniu ADDinstrukcji w pliku Dockerfile, ponieważ jest ona wykonywana tylko przez docker buildpolecenie. Jest to potrzebne, gdy inne osoby budują kontener po raz pierwszy i gdy jesteś gotowy do wdrożenia go w innych środowiskach niezwiązanych z programowaniem.
ivan.sim
3
Ale czy nie byłoby bardziej wydajne zbudowanie obrazu bez plików i użycie -vpolecenia do programowania, a inny plik Dockera utworzyłby obraz zawierający pliki ADDdo wdrożenia?
Cristian Garcia,
1
To kompromis, o którym musisz zdecydować. Wybierz to, co Ci odpowiada. Jak długo i ADDtak trwa kompilacja ? W sumie kilka sekund? Jeśli masz dwa pliki Dockerfile i udostępniasz je innym (lub publikujesz w rejestrze Docker ), który z nich jest domyślny? Będziesz mieć dodatkowe koszty utrzymania, aby upewnić się, że właściwy domyślny plik Dockerfile dotrze do właściwych użytkowników. Ale ostatecznie to Ty decydujesz, co jest dla Ciebie najlepsze. Osobiście lubię mieć pewność, że istnieje jeden i tylko jeden plik Dockerfile do zbudowania mojego kontenera.
ivan.sim
11
Swoją drogą, myślę, że dobrze jest najpierw DODAĆ, a następnie zastąpić to dodanie opcją -v na potrzeby programowania. W ten sposób nie będziesz potrzebować oddzielnych plików Dockerfiles.
Attila Szeremi