Como funcionan los Port Mappings en Docker - Puertos Externos

La red de Docker está aislada del exterior por defecto, cuando queremos conectarnos desde el exterior a un contenedor Docker usamos/creamos un mapeo de puertos y este se expone a través de localhost, 127.0.0.1 o la direccion IP.
[!note] 127.0.0.1 es una dirección de loopback que el sistema utiliza para comunicarse consigo mismo, hay un nombre resuelto automáticamente por DNS llamado localhost que apunta a 127.0.0.1.
En este ejemplo vamos a configurar un Servidor Web y una base de datos MySQL:
# Crea un directorio para tu proyecto.
mkdir port-mappings
# Crea el archivo docker-compose.yml.
touch docker-compose.yml
# Accede al archivo creado usando nano o tu editor preferido.
nano docker-compose.yml
Dentro del docker-compose.yml vamos a pegar lo siguiente:
services:
web:
image: nginx
ports:
- "28082:80"
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- '23306:3306'
[!warning] Como el contenedor de la base de datos no tiene un volumen proporcionado para la persistencia, los datos se vaciarán cada vez que se reinicie el servidor. Hablaremos de volúmenes en otra publicación
Ahora ejecutemos:
# Iniciar los contenedores definidos en docker-compose.yml
docker-compose up -d
Acceder al servidor web Web server
Al iniciar un docker-compose.yml, de forma predeterminada, los contenedores se aíslan en una red interna.
Si queremos acceder al contenedor desde nuestra máquina necesitamos utilizar un Port Mapping, en el docker-compose.yml definimos lo siguiente:
- “28082:80” para el servidor web
- http://localhost:28082
- “23306:3306” para el sevidor de base de datos
- host:localhost
- port:23306
Si queremos conectar el servidor web con el servidor MySQL, necesitamos usar el puerto interno (3306)
- host:localhost
- port:3306
De manera predeterminada, MySQL usa el puerto 3306 y el contenedor está configurado así, esto está bien, pero es posible que esté ejecutando más de un MySQL al mismo tiempo y no sea posible usar el puerto 3306 ya que este ya fue tomado por el primer servicio iniciado, aquí es cuando hacemos el mapeo, 13306, 23306 o 33067 funcionan.
- Desde fuera del contenedor Docker (entorno local), utilice el puerto expuesto 23306 (o cualquier otro definido).
- Desde dentro de la red de docker usamos 3306
Ten en cuenta que cada archivo docker-compose crea su propia red aislada, esto significa que si iniciamos App A y App B, no podrán conectarse entre ellas, a menos que creemos una red y mapeemos ambos proyectos con la misma red (lo explicaremos en otra publicación)
Tener redes docker aisladas permite tener varios proyectos con bases de datos corriendo en el puerto interno 3306 sin causar un error, correr varios servidores web se vería así:
- App A HTTP port is
28082
, Puerto interno80
- App B HTTP port is
38082
, Puerto interno80
- App C HTTP port is
48082
, Puerto interno80
services:
web:
image: nginx
ports:
- "28082:80"
web2:
image: nginx
ports:
- "38082:80"
web3:
image: nginx
ports:
- "48082:80"
# Iniciar los contenedores definidos en docker-compose.yml
docker-compose up -d
Ahora configuremos varias bases de datos con diferentes puertos expuestos:
services:
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- '23306:3306'
db2:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- '33306:3306'
db3:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'db'
MYSQL_USER: 'user'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- '43306:3306'
# Detener los contenedores
docker-compose down
Espero que estoy te ayude a entender mejor como funciona el port mapping en docker.
Recibe contenido de calidad suscribiendote al newsletter, Cero Spam!!