Docker: Træfik como proxy inverso

Træfik es una herramienta muy interesante para utilizar como proxy inverso. Es muy sencillo el desplegarlo y la configuración de este es casi automática. Es capaz de interactuar con diferentes backends como; Kubernetes, docker, mesos, swarm… además de esto, puede generar certificados válidos con let’s encrypt al vuelo. Y es capaz de crear balanceos de carga de una manera autónoma. Incluye opciones interesantes como; HTTP/2, HA en modo cluster, actualización de la configuración en caliente…

En definitiva, es una herramienta muy útil si se quiere tener varios servicios docker que requieran del mismo puerto. La arquitectura de træfik, sería la siguiente:

Las peticiones mediante SNI entran en træfik y este se encarga de redirigirlas al servicio que toque.

Aquí va el proceso de como desplegar træfik con docker y configurarlo para poder usarlo.

Despliegue

Crear el directorio de træfik

mkdir traefik && cd traefik

Descargar el archivo de configuración
Nota: revisar el archivo de configuración para adecuarlo a las necesidades. Este archivo está preparado únicamente para realizar conexiones por el puerto 80. Más adelante se explicará como hacer para conexiones cifradas.

wget https://raw.githubusercontent.com/ichasco/traefik/master/traefik.toml

Crear la red específica para træfik. Este paso es importante hacerlo, para que luego todos los contenedores que quieran hacer uso de træfik poder agregarlos a esta red

docker network create traefik

Una vez hecho esto, hay 2 formas de desplegar træfik, con docker run o con docker-compose

Docker run

docker run -d -p 8080:8080 -p 80:80 --network traefik --name traefik -v $PWD/traefik.toml:/etc/traefik/traefik.toml -v /var/run/docker.sock:/var/run/docker.sock traefik

Docker-compose

wget https://raw.githubusercontent.com/ichasco/traefik/master/docker-compose.yml

Lanzar el docker

docker-compose up -d

Una vez hecho esto, ya tenemos træfik levantado. Para acceder a el para revisar el status de los servicios, se hace mediante la web

http://dockerserver:8080

Ahora solo queda el desplegar servicios. Para la prueba, vamos a desplegar un wordpress.

Para empezar crear la carpeta

mkdir wordpress

Descargar el docker-compose de wordpress (editar lo que se necesite)

wget -O docker-compose.yml https://raw.githubusercontent.com/ichasco/traefik/master/traefik-wordpress.yml

La parte importante de este docker-compose, es la parte de labels que es donde se declaran las acciones de træfik

Para los servicios que no se quieran publicar:

labels:
   - "traefik.enable=false"

Para los servicios que se quieran publicar:

labels:
    - "traefik.backend=wp"
    - "traefik.frontend.rule=Host:wp.ichasco.com"
    - "traefik.docker.network=traefik"
  networks:
    - traefik

networks:
  traefik:
    external:
      name: traefik

Træfik tiene muchas mas opciones para definir. Mas info aquí

Ahora levantamos el wordpress

docker-compose up -d

Y automágicamente, una vez desplegado el wordpress, aparecerá en træfik

Ahora para acceder a el, necesitamos una entrada DNS que sea de la siguiente forma:

wp.ichasco.com --> dockerserver

Ya sea un CNAME o un registro A o incluso se puede poner en el /etc/hosts de nuestra máquina.

Una vez hecho esto, podemos acceder a nuestra página de la siguiente manera

http://wp.ichasco.com

Con la configuración actual de træfik, solo se puede acceder por el puerto 80. Si se quisiese acceder por el puerto 443 habría que hacer lo siguiente

HTTPS con Let’s Encrypt

Træfik tiene una opción muy interesante, que es crear certificados al vuelo con let’s encrypt. Para quien no conozca let’s encrypt, es una entidad certificadora gratuita y  conocida por todos los navegadores. Con esta opción, una vez levantado el docker con el servicio, træfik crea automáticamente un certificado y puede llegar a forzar las conexiones por el puerto 443 para garantizar la seguridad de estas.

Para hacer esto, lo único que hay que hacer es editar el traefik.toml y añadir lo siguiente:

defaultEntryPoints = ["http", "https"]

[acme]
  email = "info@ichasco.com"
  storageFile = "/etc/traefik/acme/acme.json"
  entryPoint = "https"
  acmeLogging = true
  onDemand = true
  OnHostRule = true

 [entryPoints]
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
    address = ":443"
     [entryPoints.https.tls]

Y añadir al docker-compose.yml

ports:
  - "443:443"
volumes:
  - $PWD/acme:/etc/traefik/acme

Para que træfik coja la configuración, hay que reiniciarlo

docker restart traefik_proxy_1

Escalado y balanceo

Además de todo lo comentado anteriormente, træfik es capaz de realizar balanceos round-robin automáticamente. Simplemente, escalando el servicio de docker que estemos usando con el mismo backend, træfik lo identifica y balancea las peticiones. Para hacer una prueba, vamos a escalar el wordpress

docker-compose scale wordpress=2

Si vemos los contenedores activos de docker

docker ps
CONTAINER ID          IMAGE               COMMAND                 CREATED            STATUS       PORTS                                              NAMES
ce01dad912ca    wordpress:latest    "docker-entrypoint..."    5 seconds ago Up    3 seconds       80/tcp                                       wordpress_wordpress_2
6b5dfa900823    traefik             "/traefik"                45 hours ago Up     42 seconds      0.0.0.0:80->80/tcp, 0.0.0.0:8080->8080/tcp   traefik_proxy_1
9463783ed428    wordpress:latest    "docker-entrypoint..."    2 days ago Up       41 seconds      80/tcp                                       wordpress_wordpress_1
8ec790b31890    mysql:5.7           "docker-entrypoint..."    2 days ago Up       41 seconds      3306/tcp                                     wordpress_db_1

Como se puede apreciar hay ahora 2 instancias de wordpress que esto visto en træfik sería de la siguiente manera:

Y si se cayese o saturase uno de los wordpress, las conexiones se seguirían realizando por el otro contenedor.

Y esto es todo amigos 😉

13 comments

  1. Buen Post!, gracias por compartirlo!

    lo he intentado hacer pero no me queda claro como `dockerserver` termina siendo la direccion a tu servidor. es algo automatico o es una configuracion que ya tenias?

    1. Buenas,

      correcto, dockerserver sería un registro DNS previamente creado que apunta al Host donde está instalado docker con Traefik. Traefik al funcionar con SNI tienes que tener un registro DNS ya sea en tu archivo hosts o en un servidor DNS, apuntando a la IP del host donde esté instalado.

      Si tienes alguna duda mas coméntame.

      Un saludo,

      1. en la documentación he encontrado que puedes hacer un whitelist para todos los contenedores, el problema es cuando quieres poner la whitelist en un solo container. Lo he intentado con htaccess el problema es que las peticiones vienen desde el container de traefik con lo cual o las puedo filtrar asi

  2. Buenas Ismael,
    Muy buen post!. He estado realizando un laboratorio con tus ejemplos y me han salido salvo el Let´s Encrypt, pero eso lo miraré bien. La duda que tenía es sobre el balanceador de carga y su contenido. Desconozco como podría sincronizar el contenido que hay de ambos wordpress.

    Gracias por la ayuda

    1. Buenas, los wordpress los tienes desplegados con docker-compose? es el mismo contenedor escalado? son contenedores diferentes?

      Lo ideal sería que el wordpress estuviese escalado y compartiera almacenamiento. De este modo, los datos van a ser los mismos en ambos.

      Un saludo

      1. Pues serían en diferentes contenedores sin escalar. No he caído en eso de ponerlo en el mismo volumen ¡y la cosa más sencilla!. Muchas gracias!

        Un saludo

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *