Kró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:
docker: Odpowiedź błędu z programu daemon: oci runtime error: container_linux.go: 265: uruchomienie procesu kontenera spowodowało "process_linux.go: 368: inicjalizacja kontenera spowodowała \" otwarcie / dev / ptmx: brak takiego pliku lub katalogu \ "".
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:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(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:
docker build -t my-openjdk
Biegać:
docker run --rm -it my-openjdk
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):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
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:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
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
:
docker run --rm -it -v /vol3 my-openjdk
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ę:
docker run -it -v $(pwd)/src:/src my-openjdk
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ą:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
Budujemy ten plik Dockerfile:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
Uruchamiamy to polecenie:
docker run -v $(pwd)/src:/src my-openjdk
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.