Oficjalny samouczek dotyczący platformy dokującej mówi:
Wolumen danych to specjalnie wyznaczony katalog w co najmniej jednym kontenerze, który omija Union File System. Woluminy danych zapewniają kilka przydatnych funkcji dla danych trwałych lub udostępnianych:
Woluminy są inicjowane podczas tworzenia kontenera. Jeśli obraz podstawowy kontenera zawiera dane w określonym punkcie instalacji,
te istniejące dane są kopiowane do nowego woluminu po
zainicjowaniu woluminu . (Należy zauważyć, że nie dotyczy to montowania
katalogu hosta ).
Woluminy danych można udostępniać i ponownie wykorzystywać między kontenerami.
Zmiany objętości danych są dokonywane bezpośrednio.
Zmiany ilości danych nie zostaną uwzględnione podczas aktualizacji obrazu.
Woluminy danych są trwałe, nawet jeśli sam kontener zostanie usunięty.
W Dockerfile
można określić tylko miejsce docelowe objętości wewnątrz kontenera. np /usr/src/app
.
Po uruchomieniu pojemnik, np docker run --volume=/opt:/usr/src/app my_image
, to mogą , ale nie muszą podać swój punkt montażowy ( /opt
) na komputerze hosta. Jeśli nie podasz --volume
argumentu, punkt montowania zostanie wybrany automatycznie, zwykle pod /var/lib/docker/volumes/
.
In Dockerfile you can specify only the destination of a volume inside a container. e.g. /usr/src/app.
to jest dokładnie ten wiersz, który musiałem przeczytać, aby przestać inwestować więcej czasu w to rozwiązanieKrótko mówiąc: nie, twoja
VOLUME
instrukcja jest nieprawidłowa.Pliki Dockerfile
VOLUME
określają jeden lub więcej woluminów ze ścieżkami po stronie kontenera. Ale nie pozwala autorowi obrazu określić ścieżki hosta. Po stronie hosta woluminy są tworzone z bardzo długą nazwą podobną do identyfikatora w katalogu głównym platformy Docker. To jest na mojej maszynie/var/lib/docker/volumes
.Uwaga: ponieważ automatycznie generowana nazwa jest niezwykle długa i nie ma sensu z ludzkiego punktu widzenia, tomy te są często określane jako „bez nazwy” lub „anonimowe”.
Twój przykład, w którym zastosowano „.” znak nie będzie nawet działał na moim komputerze, bez względu na to, czy kropka będzie pierwszym, czy drugim argumentem. Otrzymuję ten komunikat o błędzie:
Wiem, że to, co zostało do tej pory powiedziane, prawdopodobnie nie jest zbyt wartościowe dla kogoś, kto próbuje zrozumieć,
VOLUME
iz-v
pewnością nie dostarcza rozwiązania tego, co próbujesz osiągnąć. Miejmy nadzieję, że poniższe przykłady rzucą więcej światła na te kwestie.Mały samouczek: określanie objętości
Biorąc pod uwagę ten plik Dockerfile:
(Jeśli chodzi o wynik tego mini samouczka, nie ma znaczenia, czy określimy,
vol1 vol2
czy/vol1 /vol2
- nie pytaj mnie dlaczego)Zbuduj to:
Biegać:
Wewnątrz kontenera uruchom
ls
w wierszu poleceń, a zauważysz, że istnieją dwa katalogi;/vol1
i/vol2
.Uruchomienie kontenera powoduje również utworzenie dwóch katalogów lub „woluminów” po stronie hosta.
Mając uruchomiony kontener, wykonaj
docker volume ls
na maszynie hosta, a zobaczysz coś takiego (zastąpiłem środkową część nazwy trzema kropkami dla zwięzłości):Z powrotem w kontenerze wykonaj
touch /vol1/weird-ass-file
(tworzy pusty plik w tej lokalizacji).Ten plik jest teraz dostępny na komputerze głównym, w jednym z nienazwanych woluminów lol. Zajęło mi to dwie próby, ponieważ najpierw wypróbowałem pierwszy wymieniony wolumin, ale ostatecznie znalazłem mój plik w drugim wymienionym woluminie, używając tego polecenia na komputerze hosta:
Podobnie możesz spróbować usunąć ten plik na hoście, a zostanie on również usunięty z kontenera.
Uwaga:
_data
folder jest również nazywany „punktem montowania”.Wyjdź z kontenera i wyświetl woluminy na hoście. Oni odeszli. Użyliśmy
--rm
flagi podczas uruchamiania kontenera i ta opcja skutecznie usuwa nie tylko kontener przy wyjściu, ale także woluminy.Uruchom nowy kontener, ale określ wolumen za pomocą
-v
:To dodaje trzeci wolumin, a cały system ma trzy nienazwane woluminy. Polecenie zawiesiłoby się, gdybyśmy tylko określili
-v vol3
. Argument musi być bezwzględną ścieżką wewnątrz kontenera. Po stronie hosta nowy trzeci tom jest anonimowy i znajduje się wraz z pozostałymi dwoma tomami w formacie/var/lib/docker/volumes/
.Wspomniano wcześniej, że
Dockerfile
nie można mapować na ścieżkę hosta, co w pewnym sensie stanowi dla nas problem podczas próby przeniesienia plików z hosta do kontenera w czasie wykonywania. Inna-v
składnia rozwiązuje ten problem.Wyobraź sobie, że mam podfolder w katalogu projektu,
./src
który chcę zsynchronizować/src
wewnątrz kontenera. To polecenie załatwia sprawę:Obie strony
:
postaci oczekują bezwzględnej ścieżki. Lewa strona to bezwzględna ścieżka na komputerze hosta, a prawa strona to bezwzględna ścieżka wewnątrz kontenera.pwd
jest poleceniem, które "wypisuje bieżący / roboczy katalog". Umieszczenie polecenia$()
powoduje umieszczenie polecenia w nawiasach, uruchomienie go w podpowłoce i zwrócenie bezwzględnej ścieżki do naszego katalogu projektu.Podsumowując to wszystko, załóżmy, że mamy
./src/Hello.java
w naszym folderze projektu na komputerze głównym z następującą zawartością:Budujemy ten plik Dockerfile:
Uruchamiamy to polecenie:
To wypisuje "Hello, World!".
Najlepsze jest to, że możemy całkowicie zmodyfikować plik .java za pomocą nowej wiadomości dla innego wyjścia przy drugim uruchomieniu - bez konieczności przebudowywania obrazu =)
Uwagi końcowe
Jestem całkiem nowy w Dockerze, a wspomniany wyżej „samouczek” odzwierciedla informacje zebrane podczas 3-dniowego hackathonu z użyciem wiersza poleceń. Jestem prawie zawstydzony, że nie udało mi się podać linków do przejrzystej dokumentacji w języku angielskim, która zawierałaby moje oświadczenia, ale szczerze myślę, że jest to spowodowane brakiem dokumentacji, a nie osobistym wysiłkiem. Wiem, że przykłady działają zgodnie z reklamą, używając mojej obecnej konfiguracji, czyli „Windows 10 -> Vagrant 2.0.0 -> Docker 17.09.0-ce”.
Samouczek nie rozwiązuje problemu „jak określić ścieżkę kontenera w pliku Dockerfile i pozwolić komendzie uruchamiania określić tylko ścieżkę hosta”. Może istnieć sposób, po prostu go nie znalazłem.
Wreszcie mam przeczucie, że określanie
VOLUME
w pliku Dockerfile jest nie tylko rzadkie, ale prawdopodobnie najlepszym rozwiązaniem jest nigdy nie używaćVOLUME
. Z dwóch powodów. Pierwszy powód, który już zidentyfikowaliśmy: nie możemy określić ścieżki hosta - co jest dobrą rzeczą, ponieważ pliki Dockerfiles powinny być bardzo niezależne od specyfiki maszyny hosta. Ale drugim powodem jest to, że ludzie mogą zapomnieć o użyciu--rm
opcji podczas uruchamiania kontenera. Można by pamiętać o wyjęciu pojemnika, ale zapomnieć o usunięciu objętości. Ponadto, nawet przy najlepszej pamięci ludzkiej, ustalenie, które ze wszystkich anonimowych woluminów można bezpiecznie usunąć, może być trudnym zadaniem.źródło
docker volume prune
może służyć do czyszczenia pozostałych woluminów, które nie są dołączone do działających kontenerów. Nie mówiąc o tym, że łatwo będzie odróżnić potencjalnie ważne osoby za pomocą samego identyfikatora .../
, więcvol1
jest względny/
, co jest rozpoznawane jako/vol1
. Jeśli używaszWORKDIR
określić katalog roboczy inny niż/
,vol1
i/vol1
już nie będzie wskazywać na tym samym katalogu.Określenie
VOLUME
wiersza w pliku Dockerfile konfiguruje trochę metadanych w obrazie, ale sposób wykorzystania tych metadanych jest ważny.Po pierwsze, co zrobiły te dwie linie:
WORKDIR
Linia nie tworzy katalog, jeśli nie istnieje, i aktualizuje niektóre metadane obrazu określić wszystkie ścieżki względne, wraz z bieżącym katalogu dla komend jakRUN
będzie w tym miejscu. Znajdujący sięVOLUME
tam wiersz określa dwa woluminy , jeden jest ścieżką względną.
, a drugi/usr/src/app
, oba są po prostu tym samym katalogiem. NajczęściejVOLUME
wiersz zawiera tylko jeden katalog, ale może zawierać wiele, jak już zrobiłeś, lub może to być tablica w formacie JSON.Nie można określić źródła woluminu w pliku Dockerfile : częstym źródłem nieporozumień podczas określania woluminów w pliku Dockerfile jest próba dopasowania składni środowiska wykonawczego źródła i miejsca docelowego w czasie kompilacji obrazu, to nie zadziała . Plik Dockerfile może określać tylko miejsce docelowe woluminu. Byłby to trywialny exploit bezpieczeństwa, gdyby ktoś mógł zdefiniować źródło woluminu, ponieważ mógłby zaktualizować wspólny obraz w centrum docker, aby zamontować katalog główny w kontenerze, a następnie uruchomić proces w tle wewnątrz kontenera jako część punktu wejścia, który dodaje loginy do / etc / passwd, konfiguruje systemd do uruchomienia koparki bitcoinów przy następnym restarcie lub przeszukuje system plików w poszukiwaniu kart kredytowych, SSN i kluczy prywatnych w celu wysłania do zdalnej strony.
Co robi linia VOLUME? Jak wspomniano, niektóre metadane obrazu wskazują, że katalog wewnątrz obrazu jest woluminem. Jak są używane te metadane? Za każdym razem, gdy tworzysz kontener z tego obrazu, docker wymusi, że katalog będzie woluminem. Jeśli nie podasz woluminu w poleceniu uruchomienia ani nie utworzysz pliku, jedyną opcją dla dockera jest utworzenie anonimowego woluminu. Jest to lokalny nazwany wolumin z długim unikalnym identyfikatorem dla nazwy i bez innego wskazania, dlaczego został utworzony lub jakie dane zawiera (anonimowe woluminy są danymi, w których dane są tracone). Jeśli zastąpisz wolumin, wskazując na wolumin nazwany lub hosta, Twoje dane trafią tam.
VOLUME psuje rzeczy: nie można wyłączyć woluminu zdefiniowanego w pliku Dockerfile. Co ważniejsze,
RUN
polecenie w dockerze jest realizowane z tymczasowymi kontenerami. Te tymczasowe pojemniki otrzymają tymczasowy anonimowy wolumin. Ten anonimowy wolumin zostanie zainicjowany zawartością Twojego obrazu. Wszelkie zapisy w kontenerze z twojegoRUN
polecenia zostaną wykonane na tym woluminie. Po zakończeniu wykonywaniaRUN
polecenia zmiany w obrazie są zapisywane, a zmiany w woluminie anonimowym są odrzucane. Z tego powodu zdecydowanie odradzam definiowanie plikuVOLUME
wewnątrz Dockerfile. Powoduje to nieoczekiwane zachowanie dalszych użytkowników obrazu, którzy chcą rozszerzyć obraz o początkowe dane w lokalizacji woluminu.Jak określić głośność? Aby określić, gdzie chcesz dołączyć woluminy do obrazu, podaj plik
docker-compose.yml
. Użytkownicy mogą to zmodyfikować, aby dostosować lokalizację woluminu do lokalnego środowiska, a także przechwytuje inne ustawienia środowiska wykonawczego, takie jak publikowanie portów i sieci.Ktoś powinien to udokumentować! Oni mają. Docker zawiera ostrzeżenia dotyczące użycia VOLUME w dokumentacji w pliku Dockerfile wraz z poradą dotyczącą określenia źródła w czasie wykonywania:
źródło
Aby lepiej zrozumieć
volume
instrukcję w pliku dockerfile, poznajmy typowe użycie wolumenu w oficjalnej implementacji pliku docker mysql.Źródła: https://github.com/docker-library/mysql/blob/3362baccb4352bcf0022014f67c1ec7e6808b8c5/8.0/Dockerfile
Jest
/var/lib/mysql
to domyślna lokalizacja MySQL, w której są przechowywane pliki danych.Kiedy uruchamiasz kontener testowy tylko w celach testowych, nie możesz określić jego punktu montowania, np
wtedy instancja kontenera mysql użyje domyślnej ścieżki montowania określonej przez
volume
instrukcję w pliku dockerfile. woluminy są tworzone z bardzo długą, podobną do identyfikatora nazwą w katalogu głównym Dockera, nazywa się to woluminem „bez nazwy” lub „anonimowym”. W folderze podstawowego systemu hosta / var / lib / docker / volume.Jest to bardzo wygodne do celów szybkiego testowania bez konieczności określania punktu montażu, ale nadal można uzyskać najlepszą wydajność, używając objętości do przechowywania danych, a nie warstwy kontenera.
Do użytku formalnego będziesz musiał określić ścieżkę montowania, używając nazwanego woluminu lub wiązania, np
Polecenie montuje katalog / my / own / datadir z podstawowego systemu hosta jako / var / lib / mysql wewnątrz kontenera. Katalog danych / my / own / datadir nie zostanie automatycznie usunięty, nawet kontener zostanie usunięty.
Wykorzystanie oficjalnego obrazu mysql (sprawdź sekcję „Gdzie przechowywać dane”):
Źródła: https://hub.docker.com/_/mysql/
źródło
-v
użyj go bez ustawiania głośności w pliku DockerfileVOLUME
Polecenie wDockerfile
to całkiem prawda, całkowicie konwencjonalny, absolutnie w porządku do użytku i nie jest przestarzałe w każdym razie. Po prostu muszę to zrozumieć.Używamy go do wskazywania katalogów, w których aplikacja w kontenerze będzie dużo zapisywać. Nie używamy
VOLUME
tylko dlatego, że chcemy współdzielić hosta i kontenera, jak plik konfiguracyjny.Polecenie potrzebuje po prostu jednego parametru; ścieżka do folderu
WORKDIR
w kontenerze względem ustawienia, jeśli jest ustawiona. Następnie docker utworzy wolumen w swoim grafie (/ var / lib / docker) i zamontuje go w folderze w kontenerze. Teraz kontener będzie miał gdzie pisać z dużą wydajnością. BezVOLUME
polecenia prędkość zapisu do określonego folderu będzie bardzo niska, ponieważ teraz kontener używa swojejcopy on write
strategii w samym kontenerze. Tacopy on write
strategia jest głównym powodem istnienia tomów.Jeśli zamontujesz folder określony przez
VOLUME
polecenie, polecenie nigdy nie jest uruchamiane, ponieważVOLUME
jest wykonywane tylko podczas uruchamiania kontenera, coś w rodzajuENV
.Zasadniczo za pomocą
VOLUME
polecenia można uzyskać wydajność bez zewnętrznego montowania jakichkolwiek woluminów. Dane będą również zapisywane w przebiegach kontenerów bez żadnych zewnętrznych instalacji. Następnie, gdy będziesz gotowy, po prostu zamontuj coś na nim.Kilka dobrych przykładów użycia:
- logi
- foldery tymczasowe
Niektóre złe przypadki użycia:
- pliki statyczne
- konfiguracje
- kod
źródło
VOLUME
nic złego w określaniu katalogów konfiguracji. Jednak gdy faktycznie zamontujesz konfigurację, będziesz musiał zamontować ją w tym katalogu i dlategoVOLUME
polecenie nie działa. Dlatego nie ma sensu używaćVOLUME
polecenia na katalogu określonym dla konfiguracji. Również inicjalizacja wykresu wolumenu za pomocą pojedynczego statycznego pliku tylko do odczytu jest poważną przesadą. Więc trzymam się tego, co powiedziałem, nie ma potrzebyVOLUME
wydawania poleceń na konfiguracjach.W żadnym wypadku nie uważam użycia VOLUME za dobre, z wyjątkiem sytuacji, gdy tworzysz obraz dla siebie i nikt inny nie będzie z niego korzystał.
Negatywnie wpłynęło na mnie to, że VOLUME na obrazach podstawowych, które rozszerzyłem, i dowiedziałem się o problemie dopiero po uruchomieniu obrazu, na przykład wordpress, który deklaruje
/var/www/html
folder jako VOLUME , a to oznacza, że wszelkie pliki dodane lub zmienione etap kompilacji nie jest brany pod uwagę, a zmiany na żywo utrzymują się, nawet jeśli nie wiesz. Istnieje brzydkie obejście umożliwiające zdefiniowanie katalogu internetowego w innym miejscu, ale jest to po prostu złe rozwiązanie znacznie prostszego: po prostu usuń dyrektywę VOLUME.Możesz łatwo osiągnąć wolumen za pomocą
-v
opcji, to nie tylko wyjaśnia, jakie będą woluminy kontenera (bez konieczności patrzenia na plik Dockerfile i nadrzędne Dockerfile), ale daje to również konsumentowi opcję używać głośności lub nie.Złe jest również używanie WOLUMEN z następujących powodów, jak mówi ta odpowiedź :
Opcja cofnięcia deklaracji woluminu byłaby pomocna, ale tylko wtedy, gdy znasz woluminy zdefiniowane w pliku dockerfile, który wygenerował obraz (i nadrzędne pliki dockerfile!). Ponadto w nowszych wersjach pliku Dockerfile można dodać VOLUME i nieoczekiwanie zepsuć sytuację użytkowników obrazu.
Kolejne dobre wyjaśnienie ( o obrazie wyroczni posiadającym VOLUME , który został usunięty ): https://github.com/oracle/docker-images/issues/640#issuecomment-412647328
Więcej przypadków, w których VOLUME zepsuł dla ludzi:
Prośba przyciąganie dodać opcje resetowania Właściwości obrazu nadrzędnego (włączając objętość), został zamknięty i jest omówione są tutaj (i można zobaczyć kilka przypadków z ludzi dotkniętych negatywnie z powodu objętości określonych w dockerfiles), który ma komentarz z dobrym wyjaśnienie w stosunku do VOLUME:
Jedyną dobrą rzeczą, jaką widzę w VOLUME, jest dokumentacja i uznałbym ją za dobrą, gdyby tylko to zrobiła (bez żadnych skutków ubocznych).
TL; DR
Uważam, że najlepszym sposobem wykorzystania VOLUME jest wycofanie go.
źródło