Wiele z - co to znaczy

113

Chcę zbudować obraz dockera dla projektu Linkurious na github, który wymaga zarówno bazy danych Neo4j, jak i Node.js.

moim pierwszym podejściem było zadeklarowanie obrazu podstawowego dla mojego obrazu, zawierającego Neo4j. Dokumenty referencyjne nie definiują „obrazu podstawowego” w żaden pomocny sposób:

Obraz podstawowy: obraz, który nie ma elementu nadrzędnego, jest obrazem podstawowym

z którego przeczytałem, że mogę mieć tylko obraz podstawowy, jeśli ten obraz nie ma samego obrazu podstawowego.

ale co to jest obraz podstawowy? czy to oznacza, że ​​jeśli zadeklaruję neo4j / neo4j w dyrektywie FROM, to po uruchomieniu mojego obrazu baza danych neo uruchomi się automatycznie i będzie dostępna w kontenerze na porcie 7474?

czytając odniesienie do Dockera (patrz: https://docs.docker.com/reference/builder/#from ) widzę:

FROM może pojawić się wiele razy w jednym pliku Dockerfile w celu utworzenia wielu obrazów. Po prostu zanotuj ostatnie dane wyjściowe identyfikatora obrazu przez zatwierdzenie przed każdym nowym poleceniem FROM.

chcę utworzyć wiele obrazów? wydaje się, że chcę mieć pojedynczy obraz zawierający zawartość innych obrazów, np. neo4j i node.js

Nie znalazłem żadnej dyrektywy do deklarowania zależności w podręczniku referencyjnym. czy nie ma zależności, jak w RPM, gdzie w celu uruchomienia mojego obrazu kontekst wywołujący musi najpierw zainstalować obrazy, których potrzebuje?

Jestem zmieszany...

ekkis
źródło
Uwaga: maj 2017, masz teraz stwardnienie FROMw sposób Dockerfile. Zobacz moją zredagowaną odpowiedź poniżej.
VonC
Sprawdź, czy znajdziesz moją czystszą odpowiedź. A jeśli tak, rozważ zaakceptowanie tego.
Evan Carroll

Odpowiedzi:

113

co to jest obraz podstawowy?

Zestaw plików plus EXPOSEporty ENTRYPOINTi CMD.
Możesz dodawać pliki i budować nowy obraz na podstawie tego podstawowego obrazu, z nowym Dockerfilerozpoczynającym się od FROMdyrektywy: obraz wspomniany poniżej FROMjest „obrazem podstawowym” dla nowego obrazu.

czy to oznacza, że ​​jeśli zadeklaruję neo4j/neo4jw FROMdyrektywie, że po uruchomieniu mojego obrazu baza danych neo będzie działać automatycznie i będzie dostępna w kontenerze na porcie 7474?

Tylko jeśli nie nadpiszesz CMDi ENTRYPOINT.
Ale sam obraz wystarczy: użyłbyś FROM neo4j/neo4j, gdybyś musiał dodać pliki związane z neo4jkonkretnym zastosowaniem neo4j.

FROM może pojawić się wiele razy w jednym pliku Dockerfile

Nie: jest propozycja usunięcia tej „funkcji” mimo wszystko ( wydanie 13026 )

W numerze 14412 wspomniano:

Używanie wielu FROMnie jest tak naprawdę funkcją, ale błędem (no cóż, limit jest napięty i jest kilka przypadków użycia wielu FROMw pliku Dockerfile).


Zaktualizuj maj 2017 (18 miesięcy później), z dockerem (moby) 17.05-ce .

W jednym pliku Dockerfile można użyć wielu FROM .
Zobacz „ Wzorzec konstruktora a kompilacje wieloetapowe w Dockerze ” (autor: Alex Ellis ) i PR 31257 autorstwa Tõnis Tiigi .

Przed:

Wzorzec konstruktora polega na użyciu dwóch obrazów platformy Docker - jednego do wykonania kompilacji, a drugiego do wysłania wyników pierwszej kompilacji bez utraty łańcucha kompilacji i narzędzi w pierwszym obrazie.

Po:

Ogólna składnia obejmuje dodawanie FROMdodatkowych czasów w pliku Dockerfile - niezależnie od tego, która z tych FROMinstrukcji jest ostatnią instrukcją, jest ostatecznym obrazem podstawowym. Aby skopiować artefakty i dane wyjściowe z obrazów pośrednich, użyj COPY --from=<base_image_number>.

Pierwsza część pliku Dockerfile:

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

Druga część tego samego (!) Dockerfile:

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app    .
CMD ["./app"]  

Rezultatem byłyby dwa obrazy, jeden do tworzenia, a drugi tylko z wynikową aplikacją (dużo, dużo mniejszy)

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

multi               latest              bcbbf69a9b59        6 minutes ago       10.3MB  
golang              1.7.3               ef15416724f6        4 months ago        672MB  
VonC
źródło
2
szkoda usunięcia wielu FROM. wydaje mi się to najbardziej przydatne, szczególnie przy braku mechanizmu zależności. z RPM, na przykład, mogę zadeklarować, że mój pakiet wymaga innego pakietu do uruchomienia, więc w czasie instalacji wszystko jest skonfigurowane dla mnie. rzeczywistość jest taka, że ​​większość wszystkiego będzie wymagać wielu zależności, więc w przypadku braku wielu FROM, jak to ma działać?
ekkis
3
@ekkis, jak wspomniałem w mojej poprzedniej odpowiedzi ( stackoverflow.com/a/33295292/6309 ), uruchamiasz swój system, organizując wiele kontenerów, z których każdy zapewnia określoną usługę i komunikując się za pośrednictwem --link ( docs.docker.com/ userguide / dockerlinks /… ).
VonC
2
@VonC Jasne, w idealnym świecie, z nową aplikacją i zrozumiałymi wzorami. W międzyczasie spodziewam się, że będzie więcej przypadków, w których ludzie próbują migrować swoje rozwiązania do dockera i mają potrzeby, które nie są rozwiązywane przez sieć, takie jak zależności oprogramowania, wszystkie przy użyciu kompatybilnej bazy, ale Z wielu plików Dockerfile. Zamiast tego najlepsze, co do tej pory, to rozłupywanie ich plików Dockerfile, aby utworzyć własne.
rainabba
@rainabba Zgoda. Migracja starszych monolitów nie będzie łatwa. Ciekawe lektury : martinfowler.com/articles/… , threedots.tech/post/microservices-or-monolith-its-detail , hackernoon.com/…
VonC
2

Pierwsza odpowiedź jest zbyt złożona, historyczna i mało pouczająca jak na mój gust.


Właściwie jest to raczej proste. Docker zapewnia funkcjonalność zwaną wielostopniowymi kompilacjami, a podstawową ideą jest tutaj,

  • Uwolnij się od konieczności ręcznego usuwania tego, czego nie chcesz, zmuszając Cię do umieszczenia na białej liście tego, co chcesz,
  • Bezpłatne zasoby, które w przeciwnym razie zostałyby zajęte z powodu implementacji Dockera.

Zacznijmy od pierwszego. Bardzo często z czymś takim jak Debian zobaczysz.

RUN apt-get update \ 
  && apt-get dist-upgrade \
  && apt-get install <whatever> \
  && apt-get clean

Możemy to wszystko wyjaśnić za pomocą powyższego. Powyższe polecenie jest powiązane ze sobą, więc reprezentuje pojedynczą zmianę bez wymaganych obrazów pośrednich. Gdyby tak było napisane,

RUN apt-get update ;
RUN apt-get dist-upgrade;
RUN apt-get install <whatever>;
RUN apt-get clean;

Dałoby to 3 bardziej tymczasowe obrazy pośrednie. Po zredukowaniu do jednego obrazu pozostaje jeden problem: apt-get cleannie czyści artefaktów używanych podczas instalacji. Jeśli opiekun Debiana włączy do swojej instalacji skrypt modyfikujący system, modyfikacja ta będzie również obecna w ostatecznym rozwiązaniu (zobacz coś podobnego, pepperflashplugin-nonfreeaby zobaczyć przykład).

Korzystając z kompilacji wieloetapowej, uzyskujesz wszystkie korzyści płynące z jednej zmienionej akcji, ale będzie to wymagało ręcznego dodania do białej listy i skopiowania plików, które zostały wprowadzone do obrazu tymczasowego przy użyciu COPY --fromudokumentowanej tutaj składni. Co więcej, jest to świetne rozwiązanie, w którym nie ma alternatywy (takiej jak apt-get clean), a w przeciwnym razie miałbyś wiele niepotrzebnych plików w ostatecznym obrazie.

Zobacz też

Evan Carroll
źródło
dzięki, ale nie rozumiem, jak rozwiązujesz mój problem. dla mnie FROM jest mechanizmem dziedziczenia, a posiadanie wielu dyrektyw oznacza, że ​​mogę dziedziczyć po wielu rodzicach. w swojej odpowiedzi nie wspominasz o FROM ani o koncepcji wykorzystania pakietu oprogramowania przez innych
ekkis
1
Być może to jest zamieszanie. FROMjest zasadniczo deklaracją przestrzeni nazw. Kwalifikator jest bardziej rozszerzeniem niż dziedziczeniem. Możesz zadeklarować wiele przestrzeni nazw. Każda z tych przestrzeni nazw może rozszerzyć jedną inną przestrzeń nazw. @ekkis Jeśli druga odpowiedź Ci odpowiada, trzymaj się jej.
Evan Carroll