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

Servidor nginx

Al iniciar un docker-compose.yml, de forma predeterminada, los contenedores se aíslan en una red interna.

Red interna de docker

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

Red local y port mapping de docker

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 interno 80
  • App B HTTP port is 38082, Puerto interno 80
  • App C HTTP port is 48082, Puerto interno 80
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

Varias aplicaciones corriendo en diferentes puertos

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.