Multiple FROM: cosa significa


112

Voglio creare un'immagine docker per il progetto Linkurious su GitHub, che richiede l'esecuzione sia del database Neo4j che di Node.js.

il mio primo approccio è stato quello di dichiarare un'immagine di base per la mia immagine, contenente Neo4j. I documenti di riferimento non definiscono in alcun modo utile "immagine di base":

Immagine di base: un'immagine che non ha genitore è un'immagine di base

da cui ho letto che potrei avere un'immagine di base solo se quell'immagine non ha un'immagine di base stessa.

ma cos'è un'immagine di base? significa che se dichiaro neo4j / neo4j in una direttiva FROM, che quando la mia immagine viene eseguita il database neo verrà eseguito automaticamente e sarà disponibile all'interno del contenitore sulla porta 7474?

leggendo il riferimento Docker (vedi: https://docs.docker.com/reference/builder/#from ) vedo:

FROM può apparire più volte all'interno di un singolo Dockerfile per creare più immagini. Prendi semplicemente nota dell'ultimo output dell'ID immagine dal commit prima di ogni nuovo comando FROM.

voglio creare più immagini? sembrerebbe che quello che voglio è avere una singola immagine che contenga il contenuto di altre immagini ad esempio neo4j e node.js

Non ho trovato alcuna direttiva per dichiarare le dipendenze nel manuale di riferimento. non ci sono dipendenze come in RPM dove per eseguire la mia immagine il contesto chiamante deve prima installare le immagini di cui ha bisogno?

Non ho capito bene...


Nota: maggio 2017, ora hai più file FROMin un file Dockerfile. Vedi la mia risposta modificata di seguito.
VonC

Vedi se trovi la mia risposta più pulita. E se è così, considera di accettarlo.
Evan Carroll

Risposte:


113

cos'è un'immagine di base?

Un insieme di file, più EXPOSEporte 'd ENTRYPOINTe CMD.
Puoi aggiungere file e costruire una nuova immagine basata su quell'immagine di base, con una nuova che Dockerfileinizia con una FROMdirettiva: l'immagine menzionata dopo FROMè "l'immagine di base" per la tua nuova immagine.

significa che se dichiaro neo4j/neo4jin una FROMdirettiva, che quando viene eseguita la mia immagine il database neo verrà eseguito automaticamente e sarà disponibile all'interno del container sulla porta 7474?

Solo se non sovrascrivi CMDe ENTRYPOINT.
Ma l'immagine in sé è sufficiente: useresti un FROM neo4j/neo4jse dovessi aggiungere file relativi a neo4jper il tuo utilizzo particolare di neo4j.

FROM può apparire più volte all'interno di un singolo Dockerfile

non: c'è una proposta per rimuovere comunque quella "caratteristica" ( problema 13026 )

Il numero 14412 menziona:

L'utilizzo di più FROMnon è davvero una funzionalità ma un bug (vabbè, il limite è stretto e ci sono pochi casi d'uso per più FROMin un Dockerfile).


Aggiornamento maggio 2017 (18 mesi dopo), con docker (moby) 17.05-ce .

È possibile utilizzare più FROM in un singolo Dockerfile.
Vedi " Builder pattern vs. build multi-stage in Docker " (di Alex Ellis ) e PR 31257 di Tõnis Tiigi .

Prima:

Il modello builder prevede l'utilizzo di due immagini Docker: una per eseguire una build e un'altra per inviare i risultati della prima build senza la penalità della catena di build e degli strumenti nella prima immagine.

Dopo:

La sintassi generale prevede l'aggiunta di FROMulteriori volte all'interno del Dockerfile, a seconda di quale sia l'ultima FROMistruzione è l'immagine di base finale. Per copiare artefatti e output da immagini intermedie utilizzare COPY --from=<base_image_number>.

Prima parte del 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 .

Seconda parte dello stesso (!) 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"]  

Il risultato sarebbe due immagini, una per la creazione, una con solo l'app risultante (molto, molto più piccola)

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

multi               latest              bcbbf69a9b59        6 minutes ago       10.3MB  
golang              1.7.3               ef15416724f6        4 months ago        672MB  

2
peccato per la rimozione di più FROM. mi sembra molto utile, soprattutto in assenza di meccanismo di dipendenza. con gli RPM, ad esempio, posso dichiarare che il mio pacchetto necessita di un altro pacchetto per essere eseguito, quindi al momento dell'installazione tutto viene impostato per me. la realtà è che quasi tutto richiederà più dipendenze, quindi in assenza di più FROM, come dovrebbe funzionare?
ekkis

3
@ekkis come ho menzionato nella mia risposta precedente ( stackoverflow.com/a/33295292/6309 ), esegui il tuo sistema orchestrando più contenitori, ognuno fornendo un servizio particolare e comunicando attraverso --link ( docs.docker.com/ userguide / dockerlinks /… ).
VonC

2
@VonC Certo, in un mondo ideale, con una nuova app e tutti gli schemi compresi. Nel frattempo, mi aspetto che ci siano più istanze di persone che cercano di migrare le loro soluzioni in docker e hanno esigenze che non sono risolte dalla rete, come le dipendenze software, tutte utilizzando una base compatibile, ma DA più Dockerfile. Invece, il meglio che riesco a capire finora è l'hacking dei loro Dockerfile per crearne uno mio.
rainabba

@rainabba d'accordo. I monoliti legacy non verranno migrati facilmente. Letture interessanti: martinfowler.com/articles/… , threedots.tech/post/microservices-or-monolith-its-detail , hackernoon.com/…
VonC

2

La prima risposta è troppo complessa, storica e poco informativa per i miei gusti.


In realtà è piuttosto semplice. Docker fornisce una funzionalità chiamata build multi-fase l'idea di base qui è quella di,

  • Liberarti dal dover rimuovere manualmente ciò che non vuoi, costringendoti a inserire nella whitelist ciò che desideri,
  • Risorse gratuite che altrimenti verrebbero utilizzate a causa dell'implementazione di Docker.

Cominciamo con il primo. Molto spesso con qualcosa come Debian vedrai.

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

Possiamo spiegare tutto questo nei termini di quanto sopra. Il comando di cui sopra è concatenato insieme quindi rappresenta un singolo cambiamento senza immagini intermedie richieste. Se fosse scritto così,

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

Risulterebbe in altre 3 immagini intermedie temporanee. Dopo averlo ridotto a un'immagine, resta un problema: apt-get cleannon ripulisce gli artefatti utilizzati nell'installazione. Se un manutentore Debian include nella sua installazione uno script che modifica il sistema, tale modifica sarà presente anche nella soluzione finale (vedere qualcosa di simile pepperflashplugin-nonfreeper un esempio di questo).

Utilizzando una build in più fasi si ottengono tutti i vantaggi di una singola azione modificata, ma sarà necessario inserire manualmente nella whitelist e copiare i file che sono stati introdotti nell'immagine temporanea utilizzando la COPY --fromsintassi qui documentata. Inoltre, è un'ottima soluzione dove non ci sono alternative (come un apt-get clean) e altrimenti avresti molti file non necessari nell'immagine finale.

Guarda anche


grazie ma non vedo come stai affrontando il mio problema. per me, FROM è un meccanismo di ereditarietà e avere più direttive significa che posso ereditare da più genitori. nella tua risposta non fai menzione di FROM o del concetto di trarre vantaggio dalla confezione del software da parte di altri
ekkis

1
Forse è questa la confusione. FROMè principalmente una dichiarazione dello spazio dei nomi. Il qualificatore è più simile a un'estensione che a un'eredità. Puoi dichiarare più spazi dei nomi. E ciascuno di questi spazi dei nomi può estendere un altro spazio dei nomi. @ekkis Se l'altra risposta funziona per te, allora resta fedele.
Evan Carroll
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.