Docker montowanie woluminów na hoście

136

Udało mi się udostępniać foldery między kontenerem docker z woluminami przy użyciu

docker run -v /host/path:/container/path ...

Ale moje pytanie brzmi, jaka jest różnica między tym a użyciem VOLUMEpolecenia w pliku Dockerfile

VOLUME /path

Używam obrazu z VOLUMEpoleceniem i chciałbym wiedzieć, jak udostępnić go mojemu gospodarzowi. Zrobiłem to za pomocą -vpowyższego polecenia, ale nie wiedziałem, czy potrzebuję zarówno -vi VOLUME.

Jeff Storey
źródło

Odpowiedzi:

156

VOLUMEPolecenie zamontuje katalog wewnątrz pojemnika i przechowywać dowolne pliki utworzone lub edytowane wewnątrz tego katalogu na dysku gospodarze poza struktury plików pojemnik , z pominięciem systemu plików union.

Chodzi o to, że woluminy mogą być współużytkowane między kontenerami docker i pozostaną w pobliżu, dopóki istnieje kontener (uruchomiony lub zatrzymany), który się do nich odwołuje.

Możesz mieć inne kontenery, aby montować istniejące woluminy (efektywnie współużytkując je między kontenerami) za pomocą --volumes-frompolecenia podczas uruchamiania kontenera.

Podstawowa różnica pomiędzy VOLUMEi -vjest to: -vzamontuje istniejących plików z poziomu systemu operacyjnego wewnątrz pojemnika Döcker i VOLUMEbędzie tworzyć nową, pustą przestrzeń na hoście i zamontować go wewnątrz pojemnika.

Przykład:

  1. Masz plik Dockerfile, który definiuje plik VOLUME /var/lib/mysql.
  2. Tworzysz obraz dockera i oznaczasz go some-volume
  3. Uruchom kontener

I wtedy,

  1. Masz inny obraz dokera, którego chcesz użyć z tego woluminu
  2. Uruchamiasz kontener Dockera z następującymi elementami: docker run --volumes-from some-volume docker-image-name:tag
  3. Teraz masz uruchomiony kontener docker, który będzie miał wolumin z some-volumezamontowany w/var/lib/mysql

Uwaga: użycie --volumes-fromspowoduje zamontowanie wolumenu na wszystkim, co istnieje w lokalizacji wolumenu. To znaczy, jeśli miałeś rzeczy /var/lib/mysql, zostaną one zastąpione zawartością woluminu.

Chris McKinnel
źródło
12
Co się stanie, jeśli użyję opcji -v w katalogu, który został już określony w VOLUME?
Jeff Storey
6
--volumes-fromzamontuje cię VOLUMEna wszystko, co określisz -v. Co ciekawe, wygląda na to, że uruchomienie kontenera w trybie uprzywilejowanym ( docker run --privileged) i umounting /var/lib/mysqlpo prostu pozostawi pusty katalog, więc twój -vmount jest całkowicie ignorowany, gdy jest w konflikcie z plikiem VOLUME.
Chris McKinnel,
2
Mówisz, że woluminy są przechowywane tak długo, jak odwołuje się do nich kontener, a widziałem to gdzie indziej. Docs.docker.com/userguide/dockervolumes mówi „ Woluminy danych są zaprojektowane tak, aby utrwalać dane, niezależnie od cyklu życia kontenera. Dlatego też Docker nigdy nie usuwa automatycznie woluminów po usunięciu kontenera ani woluminów„ odśmiecania ”, które już nie są do którego odwołuje się kontener ”. Jedno z tych stwierdzeń musi być błędne.
mc0e
1
Pliki znajdujące się w wolumenie są przechowywane na dysku, gdy kontener nie odwołuje się już do niego, ale sam wolumin nie jest już użyteczny (chyba że wiesz dokładnie, jak ręcznie podłączyć wolumin do kontenera, ale nawet wtedy nie robię wiem, czy jest to możliwe). Kiedy mówię, że już nie nadaje się do użytku, mam na myśli, że nie możesz użyć --volumes-from, aby go użyć. Kiedy powyżej mówią „zbieranie śmieci”, mają na myśli usunięcie plików z dysku, które były w woluminie.
Chris McKinnel
1
Można ich używać przy użyciu opcji -v, ale nie --volumes-from. Volumes-from przyjmuje nazwę kontenera, z którego pobierane są dane o objętości (uważam, że zajmuje to WSZYSTKIE punkty objętości). Jednak w przypadku samego -v podręcznik wspomina, że ​​można podać nazwany wolumin do -v w postaci named-volume:/path/in/container. Nienazwane woluminy otrzymują skróty dla nazw i te skróty można podać zamiast ścieżki hosta, aby uzyskać dostęp do osieroconych woluminów. :) Pamiętaj, volume lsmoże nie pokazać ich wszystkich - spróbuj docker volume ls -f dangling=trueteż.
Jasmine Hegman
47

Dodam własną odpowiedź, ponieważ uważam, że inni nie rozumieją Dockera.

Używanie VOLUMEw pliku Dockerfile jest właściwym sposobem ™, ponieważ dajesz Dockerowi znać, że określony katalog zawiera trwałe dane. Docker utworzy wolumin dla tych danych i nigdy go nie usunie, nawet jeśli usuniesz wszystkie kontenery, które go używają.

Pomija również unijny system plików, dzięki czemu wolumin jest w rzeczywistości katalogiem, który jest montowany (do odczytu i zapisu lub tylko do odczytu) we właściwym miejscu we wszystkich kontenerach, które go współużytkują.

Teraz, aby uzyskać dostęp do tych danych z hosta, wystarczy sprawdzić kontener:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

Zwykle robię dowiązania symboliczne w jakimś standardowym miejscu, takim jak / srv , dzięki czemu mogę łatwo uzyskać dostęp do woluminów i zarządzać zawartymi w nich danymi (tylko w przypadku woluminów, na których Ci zależy):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log
Tobia
źródło
Co się stanie, jeśli host dockera działa na maszynie wirtualnej? Na przykład boot2docker na Macu. Wtedy te woluminy są dostępne tylko zdalnie. Ponadto podczas korzystania z woluminów w pliku Dockerfile zgodnie z opisem zawartość obrazu zostanie skopiowana do woluminu. Jednak podczas montowania do katalogu lokalnego kopiowanie to nie występuje. Czy wiesz, dlaczego tak jest? Czy istnieje sposób, aby lokalnie zamontowany wolumin, ale nadal „zacząć od nowa” z plikami z obrazu?
LostSalad
4
dzięki docker-compose możesz dokładnie to zrobić, zamontować wolumen w określonej lokalizacji systemu operacyjnego hosta . Żadne linki symboliczne nie są potrzebne ...
Hugo Koopmans
@Tobia: przykład docker-compose zobacz docs docs.docker.com/compose/compose-file/ ...
Hugo Koopmans
11

OBJĘTOŚĆ służy Dockerfiledo odsłonięcia objętości używanej przez inne pojemniki. Przykład, utwórz Dockerfilejako:

OD Ubuntu: 14.04.2018

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

zbuduj obraz:

$ docker build -t testing_volume .

Uruchom kontener, powiedzmy container1:

$ docker run -it <image-id of above image> bash

Teraz uruchom kolejny kontener z opcją woluminy z jako (powiedzmy-kontener2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

Otrzymasz wszystkie dane z /myvolkatalogu kontener 1 do kontenera 2 w tej samej lokalizacji.

-vopcja jest podawana w czasie wykonywania kontenera, który służy do montowania katalogu kontenera na hoście. Jest prosty w użyciu, wystarczy podać -vopcję z argumentem jako <host-path>:<container-path>. Cała komenda może być jak$ docker run -v <host-path>:<container-path> <image-id>

Yogesh Jilhawar
źródło
8

Zasadniczo VOLUMEi -vopcja są prawie równe. Oznacza to „konkretny katalog montowania w kontenerze”. Na przykład VOLUME /datai -v /datama dokładnie to samo znaczenie. Jeśli uruchomisz obraz VOLUME /dataz -v /dataopcją lub z opcją, /datakatalog zostanie zamontowany w Twoim kontenerze. Ten katalog nie należy do Twojego kontenera.

Wyobraź sobie, że dodajesz pliki do /datakontenera, a następnie zatwierdzasz kontener do nowego obrazu. W katalogu danych nie ma żadnych plików, ponieważ zamontowany /datakatalog należy do oryginalnego kontenera.

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

Ten zamontowany katalog /datajest używany do przechowywania danych, które nie należą do Twojej aplikacji. Możesz też wstępnie zdefiniować katalog danych, który nie należy do kontenera, używając VOLUME.

Różnica między opcjami Volumei -vpolega na tym, że można ich używać -vdynamicznie podczas uruchamiania kontenera. Oznacza to, że możesz dynamicznie montować jakiś katalog. Inną różnicą jest to, że możesz zamontować katalog hosta w kontenerze za pomocą-v

nacyot
źródło
8

To pochodzi z samej dokumentacji Dockera, może być pomocne, proste i jasne:

„Katalog hosta jest z natury zależny od hosta. Z tego powodu nie można zamontować katalogu hosta z pliku Dockerfile, instrukcja VOLUME nie obsługuje przekazywania katalogu hosta, ponieważ zbudowane obrazy powinny być przenośne. katalog nie byłby dostępny na wszystkich potencjalnych hostach. ”.

Vennesa
źródło
0

Jeśli przyjechałeś tutaj, ponieważ szukałeś prostego sposobu na przeglądanie VOLUME:

  1. Znajdź nazwę woluminu za pomocą docker volume list
  2. Zamknij wszystkie uruchomione kontenery, do których jest dołączony ten wolumin
  3. Biegać docker run -it --rm --mount source=[NAME OF VOLUME],target=/volume busybox
  4. Muszla się otworzy. cd /volumeaby wprowadzić głośność.
flix
źródło