Qual è la differenza tra “expose” e “publish” in Docker?

Sto facendo esperimenti con Dockerfiles e penso di capire la maggior parte della logica. Tuttavia, non vedo la differenza tra “esporre” e “pubblicare” una porta in questo contesto.

Tutte le esercitazioni che ho visto prima includono il comando EXPOSE nel Dockerfile:

 ... EXPOSE 8080 ... 

Quindi creano un’immagine da questo Dockerfile:

 $ docker build -t an_image - < Dockerfile 

E quindi pubblica la stessa porta come sopra durante l’esecuzione dell’immagine:

 $ docker run -d -p 8080 an_image 

o pubblicare tutte le porte usando

 $ docker run -d -P an_image 

Qual è il punto di esposizione di una porta nel Dockerfile, se verrà comunque pubblicata? Ci sarebbe mai bisogno di esporre prima una porta e non pubblicarla più tardi? Effettivamente, vorrei specificare tutte le porte che userò nel Dockerfile quando creo l’immagine, e quindi non disturbarmi più con esse, eseguendole semplicemente con:

 $ docker run -d an_image 

È ansible?

Fondamentalmente, hai tre opzioni:

  • Non specificare EXPOSE-p .
  • Specificare solo EXPOSE .
  • Specificare EXPOSE e -p .

Se non si specifica nessuno di questi, il servizio nel contenitore non sarà accessibile da nessuna parte tranne che dall’interno del contenitore stesso.

Se EXPOSE una porta, il servizio nel contenitore non è accessibile da Docker esterno, ma dall’interno di altri contenitori Docker. Quindi questo è un bene per la comunicazione tra container.

Se EXPOSE e -p una porta, il servizio nel contenitore è accessibile da qualsiasi luogo, anche al di fuori di Docker.

Il motivo per cui entrambi sono separati è IMHO perché

  • la scelta di una porta host dipende dall’host e quindi non appartiene al Dockerfile (altrimenti dipende dall’host),
  • e spesso è sufficiente che un servizio in un contenitore sia accessibile da altri contenitori.

La documentazione afferma esplicitamente:

L’istruzione EXPOSE espone le porte per l’uso all’interno dei collegamenti.

Ti indica anche come colbind i contenitori , che in pratica è la comunicazione inter-container di cui ho parlato.

PS: Se fai -p , ma non EXPOSE , Docker esegue un EXPOSE implicita. Questo perché se una porta è aperta al pubblico, è automaticamente aperta anche ad altri container Docker. Quindi -p include EXPOSE . Ecco perché non l’ho elencato sopra come un quarto caso.

Risposta breve:

  • EXPOSE è un modo di documentare
  • --publish (o -p ) è un modo di mappare una porta host a una porta del contenitore

Notare sotto le connessioni tra:

  • Dockerfile e Dockerfile
  • --publish e run-time ( docker run ... )

Esporre e pubblicare porte

Nella rete Docker, esistono due meccanismi diversi che coinvolgono direttamente le porte di rete: l’esposizione e la pubblicazione delle porte. Questo vale per la rete bridge predefinita e le reti bridge definite dall’utente.

  • Esponi le porte utilizzando la parola chiave EXPOSE nel Dockerfile o il flag --expose nella finestra mobile. L’esposizione delle porte è un modo per documentare quali porte vengono utilizzate, ma in realtà non mappa o non apre alcuna porta. L’esposizione delle porte è facoltativa .

  • Pubblichi le porte usando il --publish o --publish-all della docker run . Questo dice a Docker quali porte aprire sull’interfaccia di rete del contenitore. Quando una porta viene pubblicata, viene mappata su una porta disponibile di ordine superiore (superiore a 30000 ) sul computer host, a meno che non si specifichi la porta su cui eseguire il mapping sulla macchina host in fase di runtime. Non è ansible specificare la porta su cui eseguire la mapping sulla macchina host quando si costruisce l’immagine (nel Dockerfile), perché non c’è modo di garantire che la porta sia disponibile sul computer host su cui viene eseguita l’immagine .

da: rete di container Docker

Anche,

ESPORRE

… L’istruzione EXPOSE realtà non pubblica la porta. Funziona come un tipo di documentazione tra la persona che crea l’immagine e la persona che gestisce il contenitore, su quali porte devono essere pubblicate .

da: riferimento Dockerfile


Accesso al servizio quando --publish / --publish non sono definiti:

Alla risposta di @Golo Roden si afferma che:

“Se non si specifica nessuno di questi, il servizio nel contenitore non sarà accessibile da nessuna parte tranne che all’interno del contenitore stesso .”

Forse era il caso al momento della --publish della risposta, ma ora sembra che anche se non usi --publish o --publish , l’ host e altri containers della stessa rete saranno in grado di accedere a un servizio che potresti iniziare all’interno di quel contenitore .

Come testare questo:

Ho usato il seguente Dockerfile . Fondamentalmente, comincio con Ubuntu e installo un piccolo web server:

 FROM ubuntu RUN apt-get update && apt-get install -y mini-httpd 

build l’immagine come “testexpose” ed eseguo un nuovo contenitore con:

 docker run --rm -it testexpose bash 

All’interno del contenitore, lancio alcune istanze di mini-httpd :

 root@fb8f7dd1322d:/# mini_httpd -p 80 root@fb8f7dd1322d:/# mini_httpd -p 8080 root@fb8f7dd1322d:/# mini_httpd -p 8090 

Sono quindi in grado di utilizzare l’ curl dall’host o da altri contenitori per recuperare la pagina iniziale di mini-httpd .

EXPOSE consente di definire porte private (container) e pubbliche (host) da esporre al momento della creazione dell’immagine per quando il contenitore è in esecuzione. La porta pubblica è facoltativa, se non viene specificata una porta pubblica, verrà selezionata una porta casuale sull’host dalla finestra mobile per esporre la porta del contenitore specificata su Dockerfile.

Una buona pratica non è specificare la porta pubblica, perché limita solo un contenitore per host (un secondo contenitore getterà una porta già in uso).

È ansible utilizzare -p nella docker run per controllare quale porta pubblica le porte del container esposte saranno collegabili.

Ad ogni modo, se non usi EXPOSE-p , nessuna porta sarà esposta.

Se si usa sempre -p alla docker run non è necessario EXPOSE ma se si utilizza EXPOSE il comando di docker run può essere più semplice, EXPOSE può essere utile se non si cura quale porta verrà esposta sull’host o se si è sicuro di un solo container verrà caricato.

La maggior parte delle persone usa la finestra mobile comporre con le reti. La documentazione afferma:

La funzione di rete Docker supporta la creazione di reti senza la necessità di esporre le porte all’interno della rete, per informazioni dettagliate consultare la panoramica di questa funzionalità).

Ciò significa che se si utilizzano le reti per la comunicazione tra i contenitori non è necessario preoccuparsi di esporre le porte.

Esponi le porte utilizzando la parola chiave EXPOSE nel Dockerfile o il flag –expose nella finestra mobile. L’esposizione delle porte è un modo per documentare quali porte vengono utilizzate, ma in realtà non mappa o non apre alcuna porta. L’esposizione delle porte è facoltativa.

Fonte: github commit