Salta el contingut

Pas 4 - Publicar ports

Al pas anterior teníem NGINX funcionant, però no hi podíem accedir des del navegador. Cada contenidor té la seva pròpia xarxa aïllada: el port 80 on escolta NGINX és el port 80 del contenidor, no el de la vostra màquina. En aquest pas l'obrirem cap a fora.

Objectius del pas

  • Entendre per què un servei d'un contenidor no és accessible per defecte.
  • Publicar ports amb -p port_amfitrió:port_contenidor.
  • Executar diversos contenidors amb el mateix port intern i ports externs diferents.
  • Limitar la publicació a una interfície concreta i publicar ports UDP.

4.1 El port no està publicat

docker run -d --name web nginx:1.27-alpine
curl http://localhost:80        # falla: a l'amfitrió no hi ha res escoltant al port 80
docker rm -f web

docker ps mostrava 80/tcp a la columna PORTS: vol dir que la imatge declara que el servei usa el port 80, però aquest port no està publicat.

4.2 Publicar un port amb -p

docker run -d --name web -p 8080:80 nginx:1.27-alpine

La sintaxi és sempre -p AMFITRIÓ:CONTENIDOR: "el que arribi al port 8080 de la meva màquina, envia-ho al port 80 del contenidor".

docker ps
CONTAINER ID   IMAGE               ...   PORTS                                   NAMES
4c2d8e1f7a6b   nginx:1.27-alpine   ...   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   web

Obriu http://localhost:8080 al navegador o feu curl http://localhost:8080: veureu la pàgina de benvinguda d'NGINX. Com que està publicat a 0.0.0.0, qualsevol ordinador de la xarxa hi pot accedir amb http://IP_DE_LA_VOSTRA_MÀQUINA:8080.

flowchart LR
    N[Navegador] -->|localhost 8080| H[Amfitrio<br/>port 8080]
    H -->|redireccio de Docker| C[Contenidor web<br/>NGINX port 80]
    classDef a fill:#7C3AED,stroke:#5B21B6,color:#FFFFFF
    classDef b fill:#2563EB,stroke:#1E40AF,color:#FFFFFF
    classDef c fill:#16A34A,stroke:#166534,color:#FFFFFF
    class N a
    class H b
    class C c

Mireu els logs del contenidor mentre recarregueu la pàgina:

docker logs -f web

Cada petició del navegador apareix com una línia nova.

4.3 Diversos contenidors, el mateix port intern

Cada contenidor té la seva xarxa, per tant tots poden escoltar al port 80 intern sense conflicte. El que no pot repetir-se és el port de l'amfitrió:

docker run -d --name web1 -p 8081:80 nginx:1.27-alpine
docker run -d --name web2 -p 8082:80 nginx:1.27-alpine
docker run -d --name web3 -p 8081:80 nginx:1.27-alpine
docker: Error response from daemon: ... Bind for 0.0.0.0:8081 failed: port is already allocated.

web1 i web2 funcionen (proveu els dos ports). web3 falla perquè el port 8081 de l'amfitrió ja està ocupat. Fixeu-vos que el contenidor web3 s'ha creat igualment però ha quedat en estat Created: elimineu-lo amb docker rm web3.

No es poden afegir ports a un contenidor existent

La publicació de ports es decideix en crear el contenidor. Si us n'heu oblidat, cal eliminar-lo i crear-ne un de nou amb -p. Això no és un problema: els contenidors estan pensats per ser d'un sol ús i es recreen constantment.

4.4 Variants de publicació

Opció Efecte
-p 8080:80 Port 8080 de totes les interfícies de l'amfitrió cap al 80 del contenidor
-p 127.0.0.1:8080:80 Només accessible des de la mateixa màquina
-p 5353:53/udp Publica un port UDP (per defecte és TCP)
-p 8080:80 -p 8443:443 Diversos ports alhora
-P Publica tots els ports declarats per la imatge a ports aleatoris de l'amfitrió
docker run -d --name aleatori -P nginx:1.27-alpine
docker port aleatori         # 80/tcp -> 0.0.0.0:32768

Docker i el tallafoc a Linux

A Linux, Docker publica els ports afegint regles pròpies d'iptables/nftables. Aquestes regles s'apliquen abans que les d'eines com ufw, de manera que un port publicat amb -p 8080:80 pot quedar obert a Internet encara que ufw el bloquegi. En un servidor, publiqueu només el que calgui i, si un servei només l'ha de fer servir la mateixa màquina, lligueu-lo a 127.0.0.1. Més informació a la documentació de Docker sobre el filtratge de paquets.

Miniactivitat - Tres servidors web

  1. Arrenqueu tres servidors: nginx:1.27-alpine al port 8081, httpd:2.4-alpine (Apache) al port 8082 i caddy:2-alpine al port 8083. Consulteu a Docker Hub en quin port intern escolta cadascun.
  2. Accediu als tres des del navegador i identifiqueu quin servidor respon cada pàgina (pista: curl -I i la capçalera Server).
  3. Demaneu a un company que accedeixi al vostre port 8081 des del seu ordinador. Després recreeu el contenidor publicat només a 127.0.0.1. Encara hi pot accedir?
  4. Quina comanda us diu en quin port de l'amfitrió ha quedat publicat un contenidor arrencat amb -P?

4.5 Neteja

docker rm -f web web1 web2 aleatori

Resum del pas

Comanda Què fa
-p 8080:80 Publica el port 80 del contenidor al 8080 de l'amfitrió
-p 127.0.0.1:8080:80 Idem, només accessible localment
-p 53:53/udp Publicació UDP
-P Ports aleatoris per a tots els ports declarats
docker port NOM Mostra els ports publicats

Següent pas: NGINX funciona sense configurar res. Però moltes imatges (bases de dades, aplicacions) necessiten que els diguem com configurar-se. Al Pas 5 ho farem amb variables d'entorn.