Oryginalne pytanie: Jak korzystać z instrukcji VOLUME w Dockerfile?
Rzeczywiste pytanie, które chcę rozwiązać, to - jak zamontować woluminy hosta w kontenerach dokerów w Dockerfile podczas kompilacji, tj. Mając docker run -v /export:/export
możliwość podczas docker build
.
Powodem tego jest dla mnie budowanie rzeczy w Dockerze, nie chcę, aby te ( apt-get install
) pamięci podręczne były zamknięte w jednym oknie dokowanym , ale aby je udostępniać / ponownie wykorzystywać. To jest główny powód, dla którego pytam o to pytanie.
Najnowsza aktualizacja:
Przed dokerem v18.09 poprawną odpowiedzią powinna być ta, która zaczyna się od:
Istnieje sposób na zamontowanie woluminu podczas kompilacji, ale nie wymaga on plików Dockerfiles.
Była to jednak źle sformułowana, zorganizowana i poparta odpowiedź. Podczas ponownej instalacji mojego okna dokowanego natknąłem się na następujący artykuł:
Dokuj usługę apt-cacher-ng
https://docs.docker.com/engine/examples/apt-cacher-ng/
To rozwiązanie dokera na to / moje pytanie, nie bezpośrednio, ale pośrednio. Jest to ortodoksyjny sposób, jaki sugeruje nam doker. Przyznaję, że jest lepszy niż ten, o który tutaj pytałem.
Innym sposobem jest nowo zaakceptowana odpowiedź , np. Buildkit w wersji 18.09.
Wybierz, który Ci odpowiada.
Było: Było rozwiązanie - rocker, który nie był z Dockera, ale teraz, kiedy rocker został wycofany, ponownie przywracam odpowiedź na „Niemożliwe” .
Stara aktualizacja: więc odpowiedź brzmi „Niemożliwe”. Mogę zaakceptować to jako odpowiedź, ponieważ wiem, że problem został szeroko omówiony na stronie https://github.com/docker/docker/issues/3156 . Rozumiem, że przenośność jest najważniejszym problemem dla programistów dokerów; ale jako użytkownik dokerów muszę powiedzieć, że jestem bardzo rozczarowany tą brakującą funkcją. Pozwólcie, że zamknę mój argument cytatem ze wspomnianej dyskusji: „ Chciałbym użyć Gentoo jako obrazu podstawowego, ale zdecydowanie nie chcę, aby po zbudowaniu obrazu ponad 1 GB danych z drzewa Portage znajdowało się w żadnej z warstw. mogłyby mieć ładne, kompaktowe pojemniki, gdyby nie gigantyczne drzewo portage, które musiało pojawić się na obrazie podczas instalacji.„Tak, mogę użyć wget lub curl, aby pobrać wszystko, czego potrzebuję, ale fakt, że sama rozważność w zakresie mobilności zmusza mnie do pobrania> 1 GB drzewa Portage za każdym razem, gdy buduję obraz podstawowy Gentoo, nie jest ani wydajny, ani przyjazny dla użytkownika. więcej, repozytorium pakietów BĘDZIE ZAWSZE znajdowało się w katalogu / usr / portage, więc ZAWSZE MOŻNA PRZENOSIĆ pod Gentoo. Znowu szanuję decyzję, ale proszę pozwolić mi wyrazić moje rozczarowanie również w międzyczasie. Dzięki.
Oryginalne pytanie szczegółowo:
Z
Udostępniaj katalogi za pośrednictwem woluminów
http://docker.readthedocs.org/en/v0.7.3/use/working_with_volumes/
mówi, że funkcja Woluminy danych „była dostępna od wersji 1 Docker Remote API”. Mój doker jest w wersji 1.2.0, ale znalazłem przykład podany w powyższym artykule nie działa:
# BUILD-USING: docker build -t data .
# RUN-USING: docker run -name DATA data
FROM busybox
VOLUME ["/var/volume1", "/var/volume2"]
CMD ["/usr/bin/true"]
Jaki jest właściwy sposób w Dockerfile do montowania woluminów montowanych na hoście w kontenerach dokerów za pomocą polecenia VOLUME?
$ apt-cache policy lxc-docker
lxc-docker:
Installed: 1.2.0
Candidate: 1.2.0
Version table:
*** 1.2.0 0
500 https://get.docker.io/ubuntu/ docker/main amd64 Packages
100 /var/lib/dpkg/status
$ cat Dockerfile
FROM debian:sid
VOLUME ["/export"]
RUN ls -l /export
CMD ls -l /export
$ docker build -t data .
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM debian:sid
---> 77e97a48ce6a
Step 1 : VOLUME ["/export"]
---> Using cache
---> 59b69b65a074
Step 2 : RUN ls -l /export
---> Running in df43c78d74be
total 0
---> 9d29a6eb263f
Removing intermediate container df43c78d74be
Step 3 : CMD ls -l /export
---> Running in 8e4916d3e390
---> d6e7e1c52551
Removing intermediate container 8e4916d3e390
Successfully built d6e7e1c52551
$ docker run data
total 0
$ ls -l /export | wc
20 162 1131
$ docker -v
Docker version 1.2.0, build fa7b24f
VOLUME ~/host_dir ~/container_dir
. Dyskusja jest dość obszerna, czy istnieje krótki sposób na podsumowanie, jaki jest powód?Odpowiedzi:
Najpierw odpowiedz „dlaczego nie
VOLUME
działa?” Po zdefiniowaniuVOLUME
w Dockerfile można zdefiniować tylko cel, a nie źródło woluminu. Podczas kompilacji otrzymasz tylko anonimowy wolumin. Ten anonimowy wolumin zostanie zamontowany przy każdymRUN
poleceniu, wstępnie wypełniony zawartością obrazu, a następnie odrzucony na końcuRUN
polecenia. Zapisywane są tylko zmiany w kontenerze, a nie zmiany woluminu.Ponieważ zadano to pytanie, wydano kilka funkcji, które mogą pomóc. Pierwszy to wieloetapowe kompilacje, które pozwalają zbudować niewydajny pierwszy stopień niewykorzystanego miejsca na dysku i skopiować tylko potrzebne dane wyjściowe do ostatniego wysyłanego etapu. Drugą funkcją jest Buildkit, który radykalnie zmienia sposób budowania obrazów i dodaje nowe możliwości do kompilacji.
W przypadku kompilacji wieloetapowej miałbyś wiele
FROM
linii, z których każda rozpoczyna tworzenie oddzielnego obrazu. Domyślnie tylko ostatni obraz jest oznaczony, ale można kopiować pliki z poprzednich etapów. Standardowym zastosowaniem jest posiadanie środowiska kompilatora do tworzenia binarnego lub innego artefaktu aplikacji oraz środowiska wykonawczego jako drugiego etapu kopiowania tego artefaktu. Możesz mieć:Spowodowałoby to kompilację zawierającą tylko wynikowy plik binarny, a nie pełny katalog / export.
Buildkit wychodzi z eksperymentu w 18.09. Jest to całkowite przeprojektowanie procesu kompilacji, w tym możliwość zmiany parsera frontendu. Jedna z tych zmian parsera zaimplementowała
RUN --mount
opcję, która pozwala zamontować katalog pamięci podręcznej dla poleceń uruchamiania. Np. Tutaj jest taki, który montuje niektóre katalogi debiana (z rekonfiguracją obrazu debian, może to przyspieszyć ponowne instalowanie pakietów):Dostosowałbyś katalog pamięci podręcznej do dowolnej pamięci podręcznej aplikacji, np. $ HOME / .m2 dla maven lub /root/.cache dla golanga.
TL; DR: Odpowiedź jest tutaj: Dzięki tej
RUN --mount
składni możesz również powiązać katalogi montowania tylko do odczytu z kontekstu kompilacji. Folder musi istnieć w kontekście kompilacji i nie jest mapowany z powrotem na hosta lub klienta kompilacji:Zauważ, że ponieważ katalog jest montowany z kontekstu, jest również montowany tylko do odczytu i nie można wypychać zmian z powrotem do hosta lub klienta. Podczas kompilacji potrzebujesz wersji 18.09 lub nowszej i włącz buildkit za pomocą
export DOCKER_BUILDKIT=1
.Jeśli pojawi się błąd, że flaga mount nie jest obsługiwana, oznacza to, że albo nie włączyłeś buildkit z powyższą zmienną, albo że nie włączyłeś eksperymentalnej składni z linią składni na górze pliku Dockerfile wszelkie inne wiersze, w tym komentarze. Pamiętaj, że zmienna przełączająca buildkit będzie działać tylko wtedy, gdy instalacja dokera ma wbudowaną obsługę buildkit, która wymaga wersji 18.09 lub nowszej od Docker, zarówno na kliencie, jak i na serwerze.
źródło
Nie można użyć
VOLUME
instrukcji, aby powiedzieć dokerowi, co należy zamontować. To poważnie zakłóciłoby przenośność. Ta instrukcja mówi dokerowi, że zawartość tych katalogów nie jest wyświetlana w obrazach i można uzyskać do niej dostęp z innych kontenerów za pomocą--volumes-from
parametru wiersza polecenia. Musisz uruchomić kontener,-v /path/on/host:/path/in/container
aby uzyskać dostęp do katalogów z hosta.Montowanie woluminów hosta podczas kompilacji nie jest możliwe. Brak uprzywilejowanej kompilacji i montowanie hosta poważnie ograniczyłoby przenośność. Możesz spróbować użyć wget lub curl, aby pobrać wszystko, czego potrzebujesz do kompilacji i zainstalować.
źródło
AKTUALIZACJA: Ktoś po prostu nie przyjmie nie jako odpowiedzi i bardzo mi się podoba, szczególnie w przypadku tego konkretnego pytania.
DOBRA WIADOMOŚĆ, Teraz jest sposób -
Rozwiązaniem jest Rocker: https://github.com/grammarly/rocker
John Yani powiedział : „IMO rozwiązuje wszystkie słabe punkty Dockerfile, dzięki czemu nadaje się do rozwoju”.
Biegun
https://github.com/grammarly/rocker
Aktualizacja: Rocker został wycofany, zgodnie z oficjalnym repozytorium projektu na Github
źródło
MOUNT ~/code/docker-app-dev/new-editor/:/src/
a moje polecenie budowania Rocker jest to -rocker build -f Dockerfile .
. Co robię źle?~
jest metaznakiem powłoki Bourne'a.Rocker build
nie zezwala nadocker run
opcje wiersza polecenia, więc obecnie nie zezwala na takie rzeczy--privileged
.Istnieje sposób na zamontowanie woluminu podczas kompilacji, ale nie wymaga on plików Dockerfiles.
Techniką byłoby utworzenie kontenera z dowolnej bazy, której chcesz użyć (zamontowanie woluminów w kontenerze z
-v
opcją), uruchomienie skryptu powłoki, aby wykonać prace związane z budowaniem obrazu, a następnie zatwierdzenie kontenera jako obrazu po zakończeniu .To nie tylko pominie nadmiar plików, których nie chcesz (jest to również dobre dla bezpiecznych plików, takich jak pliki SSH), ale także tworzy pojedynczy obraz. Ma to swoje wady: polecenie commit nie obsługuje wszystkich instrukcji Dockerfile i nie pozwala ci wybrać, kiedy przerwałeś, jeśli musisz edytować skrypt kompilacji.
AKTUALIZACJA:
Na przykład,
źródło
debian:wheezy
a skrypt powłoki tobuild.sh
, jakich konkretnych instrukcji byś użył?Podczas uruchamiania kontenera tworzony jest katalog na hoście i montowany w kontenerze. Możesz dowiedzieć się, z jakim to katalogiem
Jeśli chcesz zamontować katalog z hosta w swoim kontenerze, musisz użyć
-v
parametru i określić katalog. W twoim przypadku byłoby to:Więc użyjesz folderu hosts w swoim kontenerze.
źródło
Myślę, że możesz zrobić to, co chcesz, uruchamiając kompilację za pomocą polecenia dokera, które samo jest uruchamiane w kontenerze dokera. Zobacz Docker może teraz działać w Docker | Blog Docker . Zastosowano taką technikę, która faktycznie uzyskała dostęp do zewnętrznego okna dokowanego za pomocą kontenera, np. Podczas badania, jak utworzyć najmniejszy możliwy kontener Docker | Blog Xebia .
Kolejnym istotnym artykułem jest Optymalizacja obrazów dokerów | CenturyLink Labs , który wyjaśnia, że jeśli skończysz pobierać rzeczy podczas kompilacji, możesz uniknąć marnowania miejsca na ostatecznym obrazie, pobierając, budując i usuwając pobieranie w jednym kroku RUN.
źródło
To brzydkie, ale udało mi się to pozornie:
Plik Docker:
imageBuild.sh:
Mam kompilację Java, która pobiera wszechświat do katalogu /root/.m2 i robiłem to za każdym razem .
imageBuild.sh
kopiuje zawartość tego folderu na host po kompilacji iDockerfile
kopiuje je z powrotem do obrazu dla następnej kompilacji.Jest to coś w rodzaju działania woluminu (tzn. Utrzymuje się między kompilacjami).
źródło
Oto uproszczona wersja 2-etapowego podejścia z wykorzystaniem kompilacji i zatwierdzania, bez skryptów powłoki. To wymaga:
Przy stosunkowo niewielkich zmianach dodatkowy krok dodaje tylko kilka sekund do czasu kompilacji.
Gruntownie:
W moim przypadku chcę wstępnie wygenerować plik maven toolchains.xml, ale wiele moich instalacji JDK znajduje się na woluminie, który nie jest dostępny do czasu uruchomienia. Niektóre z moich obrazów nie są kompatybilne ze wszystkimi JDKS, więc muszę przetestować kompatybilność w czasie kompilacji i warunkowo wypełnić plik toolchains.xml. Pamiętaj, że nie potrzebuję przenośnego obrazu, nie publikuję go w Docker Hub.
źródło
Jak wielu już odpowiedziało, montowanie woluminów hosta podczas kompilacji nie jest możliwe. Chciałbym tylko dodać
docker-compose
sposób, myślę, że byłoby miło mieć, głównie do użytku w programowaniu / testowaniuPlik Docker
docker-compose.yml
I poprowadź swój kontener
docker-compose up -d --build
źródło