Wed, 2023/02/08 - 20:57

No sé exactamente como voy a explicar o compartir la experiencia que tengo de usar Traefik, desde su version 1.8 hasta la actual hasta esta fecha de publicación 2.9

Básicamente es Traefik con Docker provider

Partiendo de la base de tener instalado Docker en GNU/Linux, cualquier distribución tiene su solución para instalar Docker, cualquier duda ve a la documentación oficial de como instalar Docker en GNU/Linux. Quizá será una muy simple guía en donde muestre configuraciones que me funcionan y como ir organizando la estructura a medida de que agregamos servicios a Traefik. La cosa ha cambiado bastante desde que empece a escribir VirtualHosts ahora Docker nos facilita a ser mas abstractos con la plataforma y concentrarnos más en el servicio / aplicación, junto con esto enrutar hacia servicios no podría ser más fácil. Ahora los requisitos serían.

Requisitos

  • Conocimientos básicos de network y configuración de networks, caen de perlas saber que ocurre a la hora de configurar los network en Docker
  • Kernel y utilidades de GNU/Linux
  • Conocer bien la distribución en la que te encuentras, actualmente muchas distribuciones tienen similitudes pero incluso así tienen detalles que es bueno conocer
  • Definición de lo que es un Proxy y Edge Router (básicamente lo que es Traefik)
  • Conocimientos básicos del Docker compose file
  • Ganas de estar mucho tiempo buscando la razón de porque tu servicio no está público (aunque intentaré compartir detalles y trucos para evitar eso)
  • Tener instalado Docker (no voy a cubrir aquí el modo rootless de Docker)

Puesta en Servicio de Traefik

Vamos a empezar por lo básico, levantar el contenedor de Docker, para esto usaremos siempre el modo orchestrate de Docker, que es simplemente escribir archivos "docker-compose.yml" y usar el comando "docker compose up -d"

creamos nuestro directorio

 

$ mkdir traefik-docker && cd $_
$ vim docker-compose-traefik.yml

 

 Una vez creado el directorio y abierto nuestro primer Docker compose file escribimos lo siguiente.

 

version: '3.2'

services:

  traefik:
    container_name: traefik
    image: traefik:v2.9
    restart: unless-stopped # Suelo agregar esta regla, porque en el caso de hacer 'docker compose stop' y reiniciar el sistema esto garantiza que el container no iniciara
    ports:
      - '80:80/tcp'
      - '433:433/tcp'
      - '433:433/udp' # Para usar el HTTP/3 que es experimental en la versión previa a 3.0
    networks:
      - edge-router
    volumes:
      - ./acme.json:/acme.json
      - type: bind
        source: ./dynamic/conf
        targe: /dynamic/conf
      - ./traefik.yml:traefik.yml:ro
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock
    healcheck:
      test: [ "CMD", "traefik", "healthcheck" ]
      interval: 1m
      timeout: 5s
      retries: 5

networks:
  edge-router:
    name: edge-router
    attachable: true

 

Con esto ya tenemos el fichero del primer contenedor con traefik para capturar el trafico en los puertos 80/TCP y 443/TCP y UDP (para dar soporte a HTTP/3), ahora a crear el fichero traefik.yml con el siguiente contenido

 

global:
  checkNewVersion: true

api: {}

providers:
  docker:
    exposedByDefault: false
    watch: true
  file:
    directory: /dynamic/conf
    watch: true

experimental:
  http3: true

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
    http3:
      advertisedPort: 443
    http:
      tls:
        certResolver: example_com
        domains:
          - main: example.com
            sans:
              - "www.example.com"
              - "*.example.com" # Se necesita de dnsChallenge con Let's Encrypt

certificatesResolvers:

  example_com:
    acme:
      email: tuto.traefik@example.com
      storage: acme.json
      dnsChallenge:
        provider: digitalocean
        delayBeforeCheck: '0'

 

Aquí podría detenerme y explicar punto a punto sobre el fichero de configuración de Traefik, pero quizá lo realice en otro post mas a fondo sobre la configuración, por los momentos como sus parámetros son muy explícitos doy por hecho que se entiende cada punto.

Hasta ahora tenemos configurado el docker compose file y la configuración de Traefik vamos agregar nuestra primera configuración dinámica, las configuraciones dinámicas nos ayudaran a compartir configuraciones comunes entre contenedores / servicios. Creemos un fichero en dynamic/conf/tsl.yml

 

tls:
  options:
    modern:
       minVersion: VersionTLS13
       sniStrict: true
    flex:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true

 

Esto esta configuración garantiza un certificado A+ usando la tls.flex, para servicios extrictos la tls.modern nos aseguran que solo dispositivos modernos puedan hacer el hand-shake con nuestro endpoint / router point.

Ya tenemos ahora sí todo lo necesario para ejecutar el comando docker compose -f docker-compose-traefik.yml up -d para así correr un contener con Traefik enrutando todo el tráfico de los puertos 80 y 443 hacia ese contendor usando el network host de Docker (esto es importante)

Nuestro primer servicio

Ahora que tenemos Traefik trabajando para nosotros como main entutador de los puertos comunes de Internet, vamos a crear un servicio, uno que sea útil, no un simple nginx whoami, vamos a crear un servicio de searxng, un buscador anonimo en modo self-hosting.

Vamos a crear la carpeta para este servicio para tener mas orgnizado este proyecto, dentro de la carpeta "traefik-docker" vamos a crear otra.

 

$ mkdir searxng && cd $_

 

Preparado la carpeta que nos organiza el chiringuito para tener las cosas un poco mas claras creamos nuestro docker-compose.yml

 

version: '3.7'

services:

  redis:
    container_name: redis
    image: "redis:alpine"
    command: redis-server --save "" --appendonly "no"
    restart: unless-stopped
    networks:
      - searxng
    tmpfs:
      - /var/lib/redis
    cap_drop:
      - ALL
    cap_add:
      - SETGID
      - SETUID
      - DAC_OVERRIDE
    healthcheck:
      test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
      interval: 30s
      timeout: 5s
      retries: 5

  searxng:
    container_name: searxng
    image: searxng/searxng:latest
    restart: unless-stopped
    networks:
      - searxng
      - edge-router
    volumes:
      - ./searxng/settings.yml:/etc/searxng/settings.yml:ro
    environment:
      - SEARXNG_BASE_URL=https://${SEARXNG_HOSTNAME:-localhost}/
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
        max-file: "1"
    labels:
      - traefik.enable=true

      - traefik.http.routers.searx_http.entrypoints=web
      - traefik.http.routers.searx_http.rule=Host(`searxng.example.com`)
      - traefik.http.routers.searx_http.middlewares=https-only@file

      - traefik.http.routers.searx_https.entrypoints=websecure
      - traefik.http.routers.searx_https.rule=Host(`searxng.example.com`)
      - traefik.http.routers.searx_https.tls.options=flex@file
      - traefik.http.routers.searx_https.middlewares=hardness-chained@file
      - traefik.http.routers.searx_https.service=searxng

      - traefik.http.services.searxng.loadbalancer.server.port=8080

networks:

 edge-router:
    external: true
  searxng:

 

Luego de esto, es cuestion de levantar el servicio con docker compose up -d e ir a la dirección searxng.example.com, puntos para detallar.

  • Importante estar atentos del networks en el docker-compose.yml ahí se usa el network exterior que definimos en el docker-compose de Traefik.
  • Traefik está atento del socket de docker para mirar cualquier contener que active traefik y defina reglas
  • La comunicación de trafico ocurre una vez traefik puede saber la IP del contenedor que active traefik
En un siguiente post compatire mis experiencias con un Docker Swarm mode y Traefik con un cluster de Raspberrt PI 4 y un Docker en rootless mode.