MEAN-stack и Docker. Часть 3 - Traefik reverse proxy

Третья часть цикла, посвященного контейнеризации MEAN-stack приложений, в которой мы настроим обратный прокси-сервер (reverse proxy) и балансировщик нагрузки (load balancer) Traefik.

Содержание цикла

Введение

В предыдущей части мы написали docker-compose файл, в котором настроили запуск сервисов с серверной частью приложения, клиентской частью и базой данных. Теперь же нам необходимо настроить приложение следующим образом:

  • Angular приложение должно быть доступно только по адресу docker-example.local;
  • серверное api должно принимать запросы по адресу api.docker-example.local;
  • должен быть открыт только порт 80.

Для этого нужно поднять прокси-сервер, который будет принимать все запросы на порту 80 и по хосту ретранслировать запросы на сервис client для docker-example.local и на server для api.docker-example.local.

Самое популярное решение для этих целей - использовать прокси-сервер nginx. Однако в этом проекте я попробую использовать Traefik - молодой реверс-прокси сервер и балансировщик нагрузки, который подает большие надежды.

Такой выбор был сделан по следующим причинам:

  • хорошая интеграция с Docker, Docker Swarm, Kubernetes
  • более интуитивная конфигурация и настройка
  • HTTPS от Let's Encrypt из коробки
  • еще ряд некоторых плюшек из разряда Websocket, HTTP/2, метрики Prometheus
  • интересно попробовать

Hosts

Сперва добавим наши фейковые домены в hosts:

# windows:      c:/windows/system32/drivers/etc/hosts
# ubuntu/mac:   /etc/hosts

127.0.0.1       docker-example.local
127.0.0.1       api.docker-example.local 

# Traefik Dashboard
127.0.0.1       traefik.docker-example.local

Конфигурация Traefik

Вся настройка Traefik производится в том же docker-compose файле.

docker-compose.yml

services:

  # ...

  # Добавляем сервис реверс-прокси Traefik
  reverse-proxy:
    image: traefik

    # В командах производим основную настройку
    command:

      # Включаем Traefik Dashboard (порт 8080)
      - "--api"

      # Точка входа http на порту 80 используется по умолчанию
      - "--entrypoints=Name:http Address::80"
      - "--defaultentrypoints=http"

      # Включаем режим совместимости с Docker
      - "--docker"

      # Домен по умолчанию
      - "--docker.domain=docker-example.local"

      # Следить за изменениями докера
      - "--docker.watch"

    restart: always

    # Открываем только 80 порт
    ports:
      - 80:80
    
    # Даем Traefik доступ к docker.sock 
    # для отслеживания событий Docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

    # Подключаемся к сети для прокси
    networks:
      traefik-net:
        
        # Альтернативное имя хотса для доступа по сети traefik-net
        aliases:
          - api.docker-example.local

    # В метках сервисов прописываем правила для Traefik
    labels:

      # Запросы на хост `traefik.docker-example.local`
      - traefik.frontend.rule=Host:traefik.docker-example.local

      # перенаправлять на порт 8080 (Traefik Dashboard) этого сервиса
      - traefik.port=8080

Настройка сервисов

Сами сервисы подключим к сети traefik-net, избавляемся от проброшенных портов. В labels зададим правила проксирования.

server service:

  server:
    image: myusername/public:mean-docker-server
    restart: on-failure
    depends_on:
      - db
    environment:
      - "db:uri=mongodb://db/docker"
    networks:

      # Подключаемся к сети 
      - traefik-net
      - db-net

    # В метках прописываем правила для Traefik
    labels:

      # Для реверс-прокси использовать сеть traefik-net
      - traefik.docker.network=traefik-net

      # Запросы на хост `api.docker-example.local`
      - traefik.frontend.rule=Host:api.docker-example.local

      # перенаправлять на порт 3000 этого сервиса
      - traefik.port=3000

client service:

  client:
    image: myusername/public:mean-docker-client
    restart: on-failure
    depends_on:
      - server
    networks:

      # Подключаемся к сети 
      - traefik-net

    labels:

      # Запросы на хост `docker-example.local`
      - traefik.frontend.rule=Host:docker-example.local

      # перенаправлять на порт 4000 этого сервиса
      - traefik.port=4000

db service:

  db:
    image: mongo
    restart: on-failure

    # К сети proxy-net не подключаемся
    # с сервером общаемся по db-net
    networks:
      - db-net

    labels:
      # В проксировании не нуждаемся
      - traefik.enable=false

Сети:

networks:
  traefik-net:
    external: true
  db-net:

В работе с сетями у траефика есть небольшая проблема. Дело в том, что docker compose при старте создает сети и к их именам добавляет префикс с названием проекта. Т.е. в compose файле мы указываем, что необходимо создать сеть traefik-net. В метке сервиса server мы указываем traefik, что для прокси из двух сетей необходимо использовать traefik.docker.network=traefik-net. Но после старта эта сеть не будет найдена, ибо докер назвал ее mean-docker-stack_traefik-net.

Есть два выхода:

  1. Предугадывать переименование сети и указывать traefik.docker.network=mean-docker-stack_traefik-net;
  2. Предварительно перед запуском создать external сеть traefik-net и использовать ее, указав, что она является external в docker-compose файле.

В данном случае я воспользовался вариантом №2.

Настройка HTTPS от Let's Encrypt в Traefik

Для настройки https в командах сервиса reverse-proxy добавим/заменим следующие строки:

  reverse-proxy:
    
    # ...

    command:
      - "--api"
      - "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
      - "--entrypoints=Name:https Address::443 TLS"
      - "--defaultentrypoints=http,https"
      - "--acme"
      - "--acme.storage=/etc/traefik/acme/acme.json"
      - "--acme.entryPoint=https"
      - "--acme.httpChallenge.entryPoint=http"
      - "--acme.onHostRule=true"
      - "--acme.onDemand=false"
      - "--acme.email=contact@mydomain.com"

Во время тестирования рекомендую использовать Let's Encrypt's staging server:

      - "--acme.caServer=https://acme-staging.api.letsencrypt.org/directory"

Подробнее читать в официальной документации Traefik.

Запуск

Предварительно создадим сеть traefik-net:

docker network create traefik-net

Запускаем уже известной нам командой:

docker-compose up

Рабочее приложение наблюдаем в браузере по адресу http://docker-example.local/

В следующей части попробуем развернуть наше приложение в кластере Docker Swarm.

Код проекта на GitHub >>

Часть 4 - Docker Swarm >>

Павел Прудников

Постигающий дзен фулстэк вэб буддизма

Минск, Беларусь

Подписаться на Блог MEAN stack разработчика

Получайте свежие записи прямо на ваш почтовый ящик.

Или подпишитесь на RSS с Feedly!

Комментарии

comments powered by Disqus