¿Cómo direccionar un dominio a un contenedor Docker?

Tenés tu entorno local funcionando perfecto con Docker.

Llevar la imagen al hosting y crear el contenedor no es un problema pero, cuando querés que los clientes vean el sitio… ¿qué les tenés que pasar? ¿No sería genial poder pasarles una URL con tu propio dominio?

Veamos qué necesitarías para hacerlo.

  1. Un servidor donde alojar tus contenedores
  2. Un dominio que puedas direccionar a tu servidor
  3. La configuración de DNS
  4. La configuración del webserver dentro de Docker

Asumiré que los puntos 1, 2 y 3 los tenés resueltos y me concentraré en el punto 4.

Cómo configurar Docker para que responda a un dominio único

Si se trata de un único contenedor corriendo en el servidor no es necesario hacer demasiado. Basta con asegurarse de que el contenedor esté conectado al puerto 80 del servidor.

Por ejemplo, si se inicia en un servidor un contenedor usando algo como:

docker run --restart=always -p  80:80 imagen -d

Será suficiente para dejar el contenedor corriendo en background en forma constante.

Con una configuración estándar de Apache como por ejemplo:

<VirtualHost *:80>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	ServerName www.example.com

	ServerAdmin webmaster@localhost
	DocumentRoot /var/www/html

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf
</VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Es suficiente.

En definitiva, casi que es más difícil lograr que el contenedor no quede asociado al dominio que lo contrario.

Cómo configurar Docker para que responda a diferentes dominios

Distinto, y más interesante, es el caso de querer alojar en un mismo servidor varios sitios diferentes, cada uno con su propio contenedor.

Para lograr eso se requiere algo más de maña a nivel de infraestructura.

Un webserver como Apache permite, por ejemplo, usar múltiples hosts virtuales (VirtualHost) pero, obviamente, el puerto 80 del servidor es uno solo. Esto quiere decir que hay un único proceso escuchando en el puerto 80 y, de todo el tráfico que se recibe a través de él, es su responsabilidad decidir cómo responder.

Para que a cada sitio le llegue el tráfico que le corresponde, y sólo ese tráfico, es necesario definir algún tipo de mapeo entre la petición que recibe el webserver y el host virtual que lo atenderá.

Una forma de hacer esto es asociar diferentes hosts a diferentes puertos.

<VirtualHost *:80>
	...
</VirtualHost>
<VirtualHost *:81>
	...
</VirtualHost>
<VirtualHost *:82>
	...
</VirtualHost>

Claro que, si la idea es que a todos los sitios se acceda a través del puerto estándar, esta opción queda descartada.

Otra opción disponible es desambiguar por IP:

<VirtualHost 172.21.0.1:80>
	...
</VirtualHost>
<VirtualHost 137.184.122.59:80>
	...
</VirtualHost>
<VirtualHost 93.184.216.34:80>
	...
</VirtualHost>

Esto puede funcionar si hay más de una IP pública asociada al servidor.

Lo más común, sin embargo, es desambiguar a través del ServerName:

<VirtualHost *:80>
	ServerName dominio1.com
</VirtualHost>
<VirtualHost *:80>
	ServerName dominio2.com
</VirtualHost>
<VirtualHost *:80>
	ServerName dominio3.com
</VirtualHost>

En este esquema, Apache determinará qué VirtualHost es el requerido analizando la URL. Un request de tipo http://dominio1.com será atendido siguiendo la primera definción, http://dominio2.com la segunda y http://dominio3.com la tercera.

El primer paso es claro: definir un VirtualHost por cada dominio que se quiera usar.

Segundo paso: conectar el tráfico del host al contenedor que le corresponde.

Para lograr esto es necesario contar con el módulo proxy de Apache. En el caso de Ubuntu basta con el comando sudo a2enmod proxy_http; sudo service apache2 restart para tenerlo todo listo.

Luego, por cada sitio que se quiera servir, se debe crear la configuración del VirtualHost:

<VirtualHost *:80>
    ServerName dominio1.com
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>

De esta forma, todo el tráfico que se reciba a través de http://dominio1.com será redirigido automáticamente hacia el puerto 5000 dentro del mismo servidor (De ahí el 127.0.0.1).

Por último, para cerrar el círculo se necesita contar con un contenedor Docker escuchando en el puerto seleccionado, en este caso, el 5000. Con esto será suficiente para la prueba.

docker run -p 5000:80 -v $(pwd):/var/www/html php:7.4-apache

Asumiendo que el directorio actual contiene un archivo como este:

<?php

echo phpversion();

Al abrir el navegador en http://dominio1.com/ se verá algo como:

Si aún no tenés los dominios apuntados al servidor o querés hacer pruebas en tu entorno local basta con que modifiques tu archivo /etc/hosts apuntando todos los dominios a 127.0.0.1.

El caso del segundo dominio será prácticamente igual:

<VirtualHost *:80>
    ServerName dominio2.com
    ProxyPass / http://127.0.0.1:5001/
    ProxyPassReverse / http://127.0.0.1:5001/
</VirtualHost>

La diferencia está en el puerto. El contenedor para el segundo dominio deberá estar escuchando a un puerto diferente en el host, pero éste deberá estar mapeado al puerto 80 dentro del contenedor. Por ejemplo:

docker run -p 5001:80 -v $(pwd):/var/www/html php:8.2-apache

Y, nuevamente, al abrir el navegador en http://dominio2.com verás:

Y así continúa por cada uno de los dominios que necesites apuntar

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a acceder mercados y clientes más sofisticados y exigentes

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.