Jak mogę dołączyć pliki spoza kontekstu kompilacji Dockera za pomocą polecenia „DODAJ” w pliku Dockera?
Z dokumentacji dokera:
Ścieżka musi znajdować się w kontekście kompilacji; nie można DODAĆ ../something/something, ponieważ pierwszym krokiem kompilacji dokera jest wysłanie katalogu kontekstowego (i podkatalogów) do demona dokera.
Nie chcę zrestrukturyzować całego mojego projektu tylko po to, by uwzględnić Dockera w tej sprawie. Chcę przechowywać wszystkie moje pliki Docker w tym samym podkatalogu.
Wygląda również na to, że Docker jeszcze nie obsługuje (i może nigdy nie obsługuje) dowiązań symbolicznych: polecenie Dockerfile ADD nie podąża za dowiązaniami symbolicznymi na hoście # 1676.
Jedyną rzeczą, o której mogę pomyśleć, jest krok poprzedzający kompilację, aby skopiować pliki do kontekstu kompilacji Dockera (i skonfigurować kontrolę wersji, aby ignorowała te pliki). Czy istnieje lepsze obejście tego problemu?
FROM
kontynuowanie od tego momentu . Nie zmieniłbym struktury projektu w celu dostosowania do Dockera (ani żadnych narzędzi do budowania).Odpowiedzi:
Najlepszym sposobem obejścia tego problemu jest określenie pliku Docker niezależnie od kontekstu kompilacji za pomocą opcji -f.
Na przykład to polecenie zapewni dostęp do polecenia ADD do dowolnego elementu w bieżącym katalogu.
Aktualizacja : Docker pozwala teraz mieć plik Docker poza kontekstem kompilacji (naprawiony w 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Możesz także zrobić coś takiego
źródło
dockerfile:
właściwości wbuild:
sekcji w pliku zredaguj docs.docker.com/compose/compose-file/#/compose-file-referenceADD
mieć plik spoza katalogu kontekstowego? To właśnie próbuję zrobić, ale nie sądzę, aby korzystanie z-f
zewnętrznych plików było możliwe.build: context: .., dockerfile: dir/Dockerfile
. Teraz moim kontekstem kompilacji jest katalog nadrzędny!Często używam tej
--build-arg
opcji do tego celu. Na przykład po umieszczeniu następującego pliku w Dockerfile:Możesz po prostu zrobić:
Zwróć jednak uwagę na następujące ostrzeżenie z dokumentacji Docker :
Ostrzeżenie: Nie zaleca się używania zmiennych czasu kompilacji do przekazywania sekretów, takich jak klucze github, poświadczenia użytkownika itp. Wartości zmiennych kompilacji są widoczne dla każdego użytkownika obrazu za pomocą polecenia historii dokera.
źródło
W systemie Linux możesz montować inne katalogi zamiast ich symbolicznie
Aby uzyskać więcej informacji, zobacz /superuser/842642
Nie wiem, czy coś podobnego jest dostępne dla innych systemów operacyjnych. Próbowałem też przy użyciu Samby udostępnić folder i ponownie zainstalować go w kontekście Dockera, który również działał.
źródło
Spędziłem dobry czas, próbując znaleźć dobry wzór i jak lepiej wyjaśnić, co się dzieje z tą obsługą funkcji. Uświadomiłem sobie, że najlepszym sposobem na wyjaśnienie tego jest ...
Tak więc powiedziawszy, oto przykład Dockerfile, który musi ponownie użyć pliku o nazwie
start.sh
Plik Docker
To
ALWAYS
będzie ładować z jego względnej ścieżki, posiadające aktualną dir samego siebie jakolocal
odniesienie do ścieżek można określić.Akta
Biorąc pod uwagę ten pomysł, możemy pomyśleć o posiadaniu wielu kopii pliku Docker, który tworzy określone rzeczy, ale wszystkie one potrzebują dostępu do
start.sh
.Biorąc pod uwagę tę strukturę i powyższe pliki, oto docker-compose.yml
docker-compose.yaml
shared
kontekstowym jestruntime
katalog.context
.dockerfile
.docker-compose.yml
Jest następującyall-service
jest ustawiony jako kontekst, plik współdzielonystart.sh
jest tam kopiowany, a także plik Docker określony przez każdy z nichdockerfile
.Twoje zdrowie!
źródło
a/b/c
, a następnie tak działadocker build .
nac
nie pozwoli Ci uzyskać dostęp../file-in-b
. Myślę jednak, że ogólne błędne uzasadnienie w tym (lub przynajmniej moim) było to, że kontekst jest zdefiniowany przez lokalizację podaną w pierwszym argumencie polecenia kompilacji, a nie przez lokalizację pliku Docker. Tak jak stwierdzono w zaakceptowanej odpowiedzi: froma
:docker build -f a/b/c/Dockerfile .
oznacza, że w Dockerfile.
jest teraz foldera
Jeśli przeczytasz dyskusję w numerze 2745, nie tylko doker może nigdy nie obsługiwać dowiązań symbolicznych, ale nigdy nie może obsługiwać dodawania plików poza twoim kontekstem. Wydaje się, że filozofią projektu jest to, że pliki, które wchodzą do kompilacji dokera, powinny jawnie stanowić część kontekstu lub pochodzić z adresu URL, w którym prawdopodobnie są wdrażane również w wersji stałej, aby kompilacja była powtarzalna przy dobrze znanych adresach URL lub plikach dostarczanych z pojemnik dokera.
Tylko moja opinia, ale myślę, że powinieneś dokonać restrukturyzacji, aby oddzielić kod i repozytoria dokerów. W ten sposób kontenery mogą być ogólne i pobierać dowolną wersję kodu w czasie wykonywania, a nie w czasie kompilacji.
Alternatywnie, użyj Dockera jako podstawowego artefaktu wdrażania kodu, a następnie umieść plik Dockera w katalogu głównym repozytorium kodu. jeśli wybierzesz tę trasę, prawdopodobnie warto mieć nadrzędny kontener dokujący, aby uzyskać bardziej ogólne szczegóły na poziomie systemu, i kontener podrzędny, aby skonfigurować specyficzne dla kodu.
źródło
Uważam, że prostszym obejściem jest zmiana samego „kontekstu”.
Na przykład zamiast dawać:
który ustawia bieżący katalog jako kontekst, powiedzmy, że chcesz katalog macierzysty jako kontekst, po prostu użyj:
źródło
make build
i pobiera wszystkie potrzebne pliki, jeśli zostały zaktualizowane, a następnie wywołuje odpowiednią kompilację dokera ... Muszę wykonać dodatkową pracę, ale działa bezbłędnie, ponieważ mam pełną kontrolę.Możesz także utworzyć archiwum tego, czego obraz potrzebuje najpierw i użyć go jako kontekstu.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
źródło
tar zc /dir1 /dir2 |docker build -
. W moim przypadku było to bardzo pomocne.Korzystając z docker-compose, osiągnąłem to, tworząc usługę, która montuje potrzebne mi woluminy i zatwierdzając obraz kontenera. Następnie w kolejnej usłudze polegam na wcześniej zatwierdzonym obrazie, który zawiera wszystkie dane przechowywane w zamontowanych lokalizacjach. Będziesz wtedy musiał skopiować te pliki do ich ostatecznego miejsca docelowego, ponieważ katalogi montowane na hoście nie są zatwierdzane podczas uruchamiania
docker commit
poleceniaźródło
Miałem ten sam problem z projektem i niektórymi plikami danych, których nie mogłem przenieść w kontekście repozytorium z powodów HIPPA. Skończyło się na 2 plikach Docker. Jeden buduje główną aplikację bez potrzebnych mi elementów poza kontenerem i publikuje ją w wewnętrznym repozytorium. Następnie drugi plik dokera pobiera ten obraz i dodaje dane i tworzy nowy obraz, który jest następnie wdrażany i nigdy nigdzie nie przechowywany. Nie jest to idealne, ale zadziałało w moich celach, aby ukryć poufne informacje poza repozytorium.
źródło
Łatwym obejściem może być po prostu zamontowanie woluminu (za pomocą flagi -v lub --mount) po uruchomieniu go i dostęp do plików w ten sposób.
przykład:
więcej informacji: https://docs.docker.com/storage/volumes/
źródło
docker run
jest za późno.Jak opisano w tym problemie GitHub, kompilacja faktycznie się dzieje
/tmp/docker-12345
, więc względna ścieżka podobna../relative-add/some-file
do/tmp/docker-12345
. W ten sposób szukałby/tmp/relative-add/some-file
, co jest również wyświetlane w komunikacie o błędzie. *Dołączanie plików spoza katalogu kompilacji jest niedozwolone, więc powoduje to wyświetlenie komunikatu „Zakazana ścieżka”.
źródło
Jednym szybkim i brudnym sposobem jest ustawienie kontekstu kompilacji na tyle poziomów, ile potrzebujesz - ale może to mieć konsekwencje. Jeśli pracujesz w architekturze mikrousług, która wygląda następująco:
Możesz ustawić kontekst kompilacji na
Code
katalog nadrzędny, a następnie uzyskać dostęp do wszystkiego, ale okazuje się, że przy dużej liczbie repozytoriów może to spowodować długi czas kompilacji.Przykładem może być sytuacja, w której inny zespół utrzymuje schemat bazy danych,
Repo1
a kod twojego zespołuRepo2
zależy od tego. Chcesz dokować tę zależność przy pomocy niektórych własnych danych źródłowych, nie martwiąc się o zmiany schematu lub zanieczyszczenie repozytorium drugiego zespołu (oczywiście w zależności od tego, jakie zmiany mogą być konieczne, musisz zmienić skrypty danych źródłowych). Drugie podejście jest zuchwałe, ale omija kwestię długich wersji:Utwórz skrypt sh (lub ps1),
./Code/Repo2
aby skopiować potrzebne pliki i wywołać żądane polecenia dokera, na przykład:W pliku skompilowania dokera po prostu ustaw kontekst jako
Repo2
root i użyj zawartości./db/schema
katalogu w pliku dokera, nie martwiąc się o ścieżkę. Pamiętaj, że ryzykujesz przypadkowym przekazaniem tego katalogu do kontroli źródła, ale akcje czyszczenia skryptów powinny być dość łatwe.źródło
W moim przypadku mój plik Docker jest zapisany jak szablon zawierający symbole zastępcze, które zastępuję rzeczywistą wartością za pomocą mojego pliku konfiguracyjnego.
Nie mogłem więc bezpośrednio określić tego pliku, ale potokować go w kompilacji dokera w następujący sposób:
Ale z powodu potoku
COPY
polecenie nie działało. Ale powyższy sposób rozwiązuje to przez-f -
(jawnie mówiąc, plik nie został dostarczony). Wykonując tylko-
bez-f
flagi, kontekst ORAZ plik Docker nie są udostępniane, co stanowi zastrzeżenie.źródło
Sztuką jest rozpoznanie, że możesz określić kontekst w komendzie kompilacji, aby dołączyć pliki z katalogu nadrzędnego, jeśli podasz ścieżkę Dockera, zmieniłbym mój plik Docker tak, aby wyglądał następująco:
Wtedy moje polecenie kompilacji może wyglądać następująco:
Z katalogu projektu
Z projektu / dokera
źródło