GNU/Linux >> Linux Esercitazione >  >> Panels >> Docker

Come esporre o pubblicare una porta Docker

In una configurazione a più contenitori, i servizi in esecuzione nei contenitori comunicano tra loro su una rete comune. Nella stessa configurazione, alcuni container interagiscono anche con il mondo esterno.

Questa comunicazione interna ed esterna viene gestita rispettivamente con le porte esposte e pubblicate in Docker.

In questo tutorial, parlerò della gestione delle porte in Docker. Passerò alla differenza tra l'esposizione e la pubblicazione delle porte, perché vengono utilizzate e come usarle.

Esposizione e pubblicazione di una porta in Docker

Esistono due modi per gestire le porte in Docker:esporre le porte e pubblicare le porte.

Esposizione di una porta significa semplicemente far sapere agli altri su quale porta l'applicazione containerizzata sarà in ascolto o su cui accetterà connessioni. Questo serve per comunicare con altri contenitori, non con il mondo esterno.

Pubblicazione di una porta è più come mappare le porte di un container con le porte dell'host. In questo modo, il container è in grado di comunicare con i sistemi esterni, il mondo reale, Internet.

Questa grafica ti aiuterà a capire.

Vedete, come viene mappata la porta 80 del contenitore SERVER sulla porta 80 del sistema host? In questo modo, il container è in grado di comunicare con il mondo esterno utilizzando l'indirizzo IP pubblico del sistema host.

I porti esposti, invece, non sono accessibili direttamente dall'esterno del mondo container.

Da ricordare:

  • Le porte esposte vengono utilizzate per la comunicazione interna dei container, all'interno del mondo dei container.
  • Le porte pubblicate vengono utilizzate per comunicare con i sistemi al di fuori del mondo dei container.
Qual è la differenza tra le porte docker-compose ed esporreQual è la differenza tra le porte e le opzioni di esposizione in docker-compose.yml Stack OverflowBibek Shrestha

Esposizione delle porte in Docker

Innanzitutto, esporre un porto non è strettamente necessario. Come mai? Perché la maggior parte delle immagini Docker che utilizzi nella tua configurazione hanno già una porta predefinita esposta nella loro configurazione.

Ad esempio, un'applicazione front-end containerizzata può comunicare con un database MariaDB semplicemente specificando l'IP del container e la porta su cui MariaDB accetta le connessioni (predefinito 3306).

L'esposizione aiuta in una situazione in cui non vengono utilizzate le impostazioni predefinite, come in questo caso se MariaDB non accettasse connessioni sulla porta 3306, dovrebbe essere menzionata una porta alternativa esponendola.

Esistono due modi per esporre una porta:

  1. Utilizzando EXPOSE Istruzioni per il file Docker.
  2. Utilizzo di --expose con Docker CLI o expose digitare docker-compose.

È ora di approfondire entrambi.

Metodo 1:esporre le porte tramite Dockerfile

Puoi aggiungere una semplice istruzione nel tuo Dockerfile per far sapere agli altri su quale porta la tua applicazione accetterà le connessioni.

A proposito di questa istruzione, quello che devi sapere è quanto segue:-

  • EXPOSE non aggiungi livelli aggiuntivi all'immagine della finestra mobile risultante. Aggiunge solo metadati.
  • EXPOSE è un modo per documentare la porta dell'applicazione. L'unico effetto che ha è in termini di leggibilità o comprensione dell'applicazione.

Puoi vedere come funziona l'esposizione con una semplice immagine contenitore che ho creato proprio per questo scopo. Questa immagine non fa nulla .

Estrai l'immagine.

docker pull debdutdeb/expose-demo:v1

Questa immagine espone un totale di quattro porte, elenca l'immagine usando il comando seguente.

docker image ls --filter=reference=debdutdeb/expose-demo:v1

Dai un'occhiata a SIZE colonna, dirà 0 byte.

➟ docker image ls --filter=reference=debdutdeb/expose-demo:v1
REPOSITORY              TAG       IMAGE ID       CREATED   SIZE
debdutdeb/expose-demo   v1        ad3d8ffa9bfe   N/A       0B

Il motivo è semplice, non ci sono livelli in questa immagine, tutte le istruzioni di esposizione aggiunte erano metadati, nessun livello reale.

Puoi anche ottenere il numero di livelli disponibili usando il seguente comando:-

docker image inspect -f '{{len .RootFS.Layers}}' debdutdeb/expose-demo:v1

Dovresti vedere un output come questo:-

➟ docker image inspect -f '{{len .RootFS.Layers}}' debdutdeb/expose-demo:v1 
0

Come ho detto in precedenza, le porte esposte vengono aggiunte come metadati dell'immagine, per farci sapere quali porte sta utilizzando l'applicazione.

Come vedi queste informazioni senza guardare un Dockerfile? Devi controllare l'immagine. Per essere più specifici, vedere il comando seguente, è possibile utilizzare un comando simile su qualsiasi immagine per elencare le porte esposte.

Sto usando la mia immagine di esempio per la dimostrazione.

docker image inspect -f \
	'{{range $exposed, $_ := .Config.ExposedPorts}}{{printf "%s\n" $exposed}}{{end}}' \
    debdutdeb/expose-demo:v1

Esempio di output:

➟ docker image inspect -f '{{range $exposed, $_ := .Config.ExposedPorts}}{{printf "%s\n" $exposed}}{{end}}' debdutdeb/expose-demo:v1 
443/tcp
80/tcp
8080/tcp
9090/tcp

Puoi anche confrontare questa immagine, che espone un paio di porte, con debdutdeb/noexpose-demo:v1 immagine, che non espone alcuna porta. Esegui lo stesso set di comandi anche su quell'immagine e nota la differenza.

Metodo 2:esposizione delle porte tramite CLI o docker-compose

A volte gli sviluppatori di applicazioni evitano di includere un extra EXPOSE istruzioni nel loro Dockerfile.

In tal caso, per assicurarti che altri contenitori (tramite l'API Docker) possano rilevare facilmente la porta in uso, puoi esporre più porte dopo la compilazione, come parte del processo di distribuzione.

Scegli il metodo imperativo, ovvero la CLI, o il metodo dichiarativo, ovvero comporre file.

Metodo CLI

In questo metodo, durante la creazione di un contenitore, tutto ciò che devi fare è usare il --expose opzione (tutte le volte necessarie) con il numero di porta e opzionalmente il protocollo con un / . Ecco un esempio:-

docker container run \
	--expose 80 \
    --expose 90 \
    --expose 70/udp \
    -d --name port-expose busybox:latest sleep 1d

Sto usando la busybox immagine che non espone alcuna porta per impostazione predefinita.

Metodo di composizione file

Se stai usando un file di composizione, puoi aggiungere un array expose nella definizione del servizio. Puoi convertire la distribuzione precedente in un file di composizione in questo modo:-

version: "3.7"
services:
	PortExpose:
    	image: busybox
        command: sleep 1d
        container_name: port-expose
        expose:
        	- 80
            - 90
            - 70/udp

Una volta che hai il container in esecuzione, proprio come prima puoi ispezionarlo per sapere quali porte sono esposte. Il comando è simile.

docker container inspect -f \
	'{{range $exposed, $_ := .NetworkSettings.Ports}}
    {{printf "%s\n" $exposed}}{{end}}' \
    port-expose

Esempio di output:-

➟ docker container inspect -f '{{range $exposed, $_ := .NetworkSettings.Ports}}{{printf "%s\n" $exposed}}{{end}}' port-expose 
70/udp
80/tcp
90/tcp

Pubblicazione di una porta in Docker

La pubblicazione delle porte è sinonimo di port forwarding in cui le richieste da una connessione in entrata su una porta pubblica vengono inoltrate alla porta del contenitore.

Allo stesso modo, le risposte inviate dal container attraverso la sua porta vengono inviate al client inoltrando il traffico alla porta specificata nello spazio della porta dell'host.

Esistono due modi per pubblicare un port, uno tramite la CLI e un altro utilizzando un file di composizione. Entrambi i metodi hanno anche una sintassi lunga e una sintassi breve.

Metodo 1:pubblica le porte tramite il comando Docker

Le due sintassi sono le seguenti:

  1. -p [optional_host_ip]:[host_port]:[container_port]/[optional_protocol]
  2. --publish target=[container_port],published=[optional_host_ip]:[host_port],protocol=[optional_protocol]
Per l'IP host opzionale, puoi utilizzare qualsiasi indirizzo IP associato a qualsiasi scheda di rete. Se l'IP viene omesso, la finestra mobile collegherà la porta con tutti gli indirizzi IP disponibili.

Utilizzerai di più il primo. Il secondo è più leggibile. Vediamo un esempio usando un contenitore nginx. Esegui il seguente comando:-

docker container run --rm --name nginx \
	--publish target=80,published=127.0.0.1:8081,protocol=tcp \
    -d nginx

Con questo comando sto semplicemente associando la porta 80 del contenitore alla porta 8081 del mio host su localhost. Ora se vai su http://localhost:8081 vedrai nginx in esecuzione.

Il comando precedente può essere facilmente convertito nella forma più breve in questo modo

docker container run --rm --name nginx \
	-p 80:127.0.0.1:8081/tcp -d nginx

Sebbene sia più breve, è più difficile da leggere.

Puoi anche usare -p o --publish più volte per pubblicare più porte.

Metodo 2:pubblicazione di una porta tramite un file di composizione

Per pubblicare una porta usando un file di composizione avrai bisogno di un array chiamato ports nella definizione del servizio. Questo array può essere un elenco di stringhe simile alla sintassi breve della CLI, oppure puoi utilizzare un elenco di oggetti simile alla sintassi lunga.

Se dovessi convertire la precedente distribuzione di nginx utilizzando un file di composizione con una matrice di stringhe per la sezione delle porte, sembrerebbe la seguente:-

version: "3.7"
services:
	Nginx:
    	image: nginx
		container_name: nginx
        ports:
        	- 80:127.0.0.1:8081/tcp

Lascia che ti mostri anche come utilizzare la sintassi dell'array di oggetti.

version: "3.7"
services:
	Nginx:
    	image: nginx
        container_name: nginx
        ports:
        	- target: 80
              published: 127.0.0.1:8081
              protocol: tcp

Per vedere l'elenco di tutte le porte pubblicate, puoi ispezionare il container in questo modo-

docker container inspect -f '{{range $container, $host := .NetworkSettings.Ports}}{{printf "%s -> %s\n" $container $host}}{{end}}' nginx

Se eseguito vedrai il seguente output:-

➟ docker container inspect -f '{{range $container, $host := .NetworkSettings.Ports}}{{printf "%s -> %s\n" $container $host}}{{end}}' nginx 
80/tcp -> [{127.0.0.1 8081}]

C'è un altro modo più semplice per elencare le porte pubblicate, usando la docker container port comando.

docker container port nginx

Esempio di output:-

➟ docker container port nginx
80/tcp -> 127.0.0.1:8081

Quando esporre una porta e quando pubblicarla?

Questa è una domanda giusta. L'esposizione e la pubblicazione non dovrebbero essere concorrenti. Ognuno ha uno scopo diverso. Se sei lo sviluppatore di un'immagine, esporrai le porte in modo che l'utente possa essere più sicuro di dove tentare una connessione. D'altra parte, se stai utilizzando un'immagine e devi renderla disponibile al mondo esterno, pubblicherai le porte necessarie.

Spero che questo articolo ti sia stato utile. Se hai domande, fammi sapere nei commenti in basso.


Docker
  1. Come installare Jenkins con Docker

  2. Come usare Docker Compose

  3. Come collegare i contenitori Docker

  4. Come eseguire ssh su più porte

  5. Nozioni di base su Docker:consente di esporre le porte, il collegamento delle porte e il collegamento Docker

Come installare Docker CE in Linux Mint 20

Come utilizzare Netcat per scansionare le porte aperte in Linux

Come esporre o pubblicare una porta Docker

Come rimuovere i contenitori Docker

Come fermare i container Docker

Come installare Docker su Mac